aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/trap.c4
-rw-r--r--sys/arm/allwinner/a10/a10_intc.c1
-rw-r--r--sys/arm/allwinner/a10_gpio.c3
-rw-r--r--sys/arm/allwinner/a10_hdmi.c2
-rw-r--r--sys/arm/allwinner/a10_mmc.c23
-rw-r--r--sys/arm/allwinner/a10_sramc.c1
-rw-r--r--sys/arm/allwinner/a20/a20_cpu_cfg.c1
-rw-r--r--sys/arm/allwinner/aw_ccu.c3
-rw-r--r--sys/arm/allwinner/aw_cir.c1
-rw-r--r--sys/arm/allwinner/aw_machdep.c2
-rw-r--r--sys/arm/allwinner/aw_nmi.c1
-rw-r--r--sys/arm/allwinner/aw_thermal.c77
-rw-r--r--sys/arm/allwinner/aw_ts.c1
-rw-r--r--sys/arm/allwinner/aw_wdog.c1
-rw-r--r--sys/arm/allwinner/clk/aw_gate.c1
-rw-r--r--sys/arm/allwinner/clk/aw_mmcclk.c2
-rw-r--r--sys/arm/allwinner/clk/aw_pll.c10
-rw-r--r--sys/arm/allwinner/if_emac.c1
-rw-r--r--sys/arm/allwinner/timer.c1
-rw-r--r--sys/arm/altera/socfpga/socfpga_common.c29
-rw-r--r--sys/arm/altera/socfpga/socfpga_gpio.c1
-rw-r--r--sys/arm/altera/socfpga/socfpga_manager.c1
-rw-r--r--sys/arm/altera/socfpga/socfpga_rstmgr.c8
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_ccm.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_fb.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_gpio.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_i2c.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_mmc.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_pic.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_pinctrl.c3
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_rng.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_rtc.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_timer.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_wdt.c1
-rw-r--r--sys/arm/amlogic/aml8726/uart_dev_aml8726.c1
-rw-r--r--sys/arm/annapurna/alpine/alpine_machdep.c2
-rw-r--r--sys/arm/annapurna/alpine/alpine_machdep_mp.c3
-rw-r--r--sys/arm/arm/generic_timer.c1
-rw-r--r--sys/arm/arm/gic.c3
-rw-r--r--sys/arm/arm/gic_fdt.c1
-rw-r--r--sys/arm/arm/mp_machdep.c1
-rw-r--r--sys/arm/arm/mpcore_timer.c1
-rw-r--r--sys/arm/arm/pl190.c1
-rw-r--r--sys/arm/arm/pl310.c1
-rw-r--r--sys/arm/arm/pmap-v6.c24
-rw-r--r--sys/arm/arm/pmu.c1
-rw-r--r--sys/arm/at91/at91_aic.c1
-rw-r--r--sys/arm/at91/at91_cfata.c2
-rw-r--r--sys/arm/at91/at91_common.c3
-rw-r--r--sys/arm/at91/at91_mci.c1
-rw-r--r--sys/arm/at91/at91_ohci_fdt.c1
-rw-r--r--sys/arm/at91/at91_pinctrl.c1
-rw-r--r--sys/arm/at91/at91_pio.c1
-rw-r--r--sys/arm/at91/at91_pit.c1
-rw-r--r--sys/arm/at91/at91_pmc.c1
-rw-r--r--sys/arm/at91/at91_rst.c1
-rw-r--r--sys/arm/at91/at91_sdramc.c1
-rw-r--r--sys/arm/at91/at91_shdwc.c1
-rw-r--r--sys/arm/at91/at91_spi.c1
-rw-r--r--sys/arm/at91/at91_tcb.c1
-rw-r--r--sys/arm/at91/at91_twi.c1
-rw-r--r--sys/arm/at91/at91_wdt.c1
-rw-r--r--sys/arm/at91/if_ate.c1
-rw-r--r--sys/arm/at91/if_macb.c1
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c4
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_dma.c1
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_fb.c9
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_fbd.c1
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_ft5406.c1
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_intr.c1
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_machdep.c10
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_sdhci.c1
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_spi.c1
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_systimer.c1
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_wdog.c1
-rw-r--r--sys/arm/conf/GENERIC27
-rw-r--r--sys/arm/conf/PANDABOARD3
-rw-r--r--sys/arm/freescale/imx/imx51_ccm.c1
-rw-r--r--sys/arm/freescale/imx/imx51_ipuv3.c5
-rw-r--r--sys/arm/freescale/imx/imx51_ipuv3_fbd.c5
-rw-r--r--sys/arm/freescale/imx/imx6_audmux.c1
-rw-r--r--sys/arm/freescale/imx/imx6_ipu.c1
-rw-r--r--sys/arm/freescale/imx/imx6_sdma.c1
-rw-r--r--sys/arm/freescale/imx/imx6_ssi.c9
-rw-r--r--sys/arm/freescale/imx/imx_gpio.c1
-rw-r--r--sys/arm/freescale/imx/imx_gpt.c1
-rw-r--r--sys/arm/freescale/imx/imx_i2c.c1
-rw-r--r--sys/arm/freescale/imx/imx_iomux.c3
-rw-r--r--sys/arm/freescale/imx/imx_wdog.c1
-rw-r--r--sys/arm/freescale/imx/tzic.c1
-rw-r--r--sys/arm/freescale/vybrid/vf_adc.c1
-rw-r--r--sys/arm/freescale/vybrid/vf_anadig.c1
-rw-r--r--sys/arm/freescale/vybrid/vf_common.c29
-rw-r--r--sys/arm/freescale/vybrid/vf_dcu4.c31
-rw-r--r--sys/arm/freescale/vybrid/vf_dmamux.c1
-rw-r--r--sys/arm/freescale/vybrid/vf_edma.c5
-rw-r--r--sys/arm/freescale/vybrid/vf_ehci.c2
-rw-r--r--sys/arm/freescale/vybrid/vf_gpio.c1
-rw-r--r--sys/arm/freescale/vybrid/vf_i2c.c1
-rw-r--r--sys/arm/freescale/vybrid/vf_iomuxc.c6
-rw-r--r--sys/arm/freescale/vybrid/vf_machdep.c2
-rw-r--r--sys/arm/freescale/vybrid/vf_mscm.c1
-rw-r--r--sys/arm/freescale/vybrid/vf_port.c1
-rw-r--r--sys/arm/freescale/vybrid/vf_sai.c17
-rw-r--r--sys/arm/freescale/vybrid/vf_spi.c1
-rw-r--r--sys/arm/freescale/vybrid/vf_src.c1
-rw-r--r--sys/arm/freescale/vybrid/vf_tcon.c1
-rw-r--r--sys/arm/lpc/lpc_fb.c4
-rw-r--r--sys/arm/lpc/lpc_intc.c2
-rw-r--r--sys/arm/lpc/lpc_machdep.c2
-rw-r--r--sys/arm/lpc/lpc_timer.c5
-rw-r--r--sys/arm/mv/armadaxp/armadaxp.c1
-rw-r--r--sys/arm/mv/gpio.c24
-rw-r--r--sys/arm/mv/mv_common.c14
-rw-r--r--sys/arm/mv/mv_machdep.c25
-rw-r--r--sys/arm/mv/mv_pci.c4
-rw-r--r--sys/arm/mv/mv_ts.c1
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_machdep.c1
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_pmc.c1
-rw-r--r--sys/arm/nvidia/tegra_abpmisc.c1
-rw-r--r--sys/arm/nvidia/tegra_ahci.c1
-rw-r--r--sys/arm/nvidia/tegra_efuse.c1
-rw-r--r--sys/arm/nvidia/tegra_gpio.c1
-rw-r--r--sys/arm/nvidia/tegra_i2c.c1
-rw-r--r--sys/arm/nvidia/tegra_pcie.c1
-rw-r--r--sys/arm/nvidia/tegra_rtc.c1
-rw-r--r--sys/arm/nvidia/tegra_uart.c3
-rw-r--r--sys/arm/nvidia/tegra_usbphy.c1
-rw-r--r--sys/arm/rockchip/files.rk30xx1
-rw-r--r--sys/arm/rockchip/rk30xx_gpio.c16
-rw-r--r--sys/arm/rockchip/rk30xx_grf.c1
-rw-r--r--sys/arm/rockchip/rk30xx_machdep.c2
-rw-r--r--sys/arm/rockchip/rk30xx_pmu.c1
-rw-r--r--sys/arm/rockchip/rk30xx_wdog.c1
-rw-r--r--sys/arm/samsung/exynos/exynos5_common.c22
-rw-r--r--sys/arm/ti/aintc.c5
-rw-r--r--sys/arm/ti/am335x/am335x_ecap.c1
-rw-r--r--sys/arm/ti/am335x/am335x_ehrpwm.c1
-rw-r--r--sys/arm/ti/am335x/am335x_gpio.c6
-rw-r--r--sys/arm/ti/am335x/am335x_lcd.c4
-rw-r--r--sys/arm/ti/am335x/am335x_lcd_syscons.c15
-rw-r--r--sys/arm/ti/am335x/am335x_musb.c1
-rw-r--r--sys/arm/ti/am335x/am335x_prcm.c1
-rw-r--r--sys/arm/ti/am335x/am335x_pwmss.c1
-rw-r--r--sys/arm/ti/am335x/am335x_scm_padconf.c2
-rw-r--r--sys/arm/ti/am335x/am335x_scm_padconf.h2
-rw-r--r--sys/arm/ti/am335x/am335x_usbss.c1
-rw-r--r--sys/arm/ti/cpsw/if_cpsw.c1
-rw-r--r--sys/arm/ti/omap4/files.omap42
-rw-r--r--sys/arm/ti/omap4/omap4_gpio.c5
-rw-r--r--sys/arm/ti/omap4/omap4_mp.c8
-rw-r--r--sys/arm/ti/omap4/omap4_mp.h33
-rw-r--r--sys/arm/ti/omap4/omap4_prcm_clks.c1
-rw-r--r--sys/arm/ti/omap4/omap4_scm_padconf.c2
-rw-r--r--sys/arm/ti/omap4/omap4_scm_padconf.h2
-rw-r--r--sys/arm/ti/omap4/pandaboard/files.pandaboard3
-rw-r--r--sys/arm/ti/omap4/pandaboard/pandaboard.c41
-rw-r--r--sys/arm/ti/omap4/pandaboard/pandaboard.h32
-rw-r--r--sys/arm/ti/omap4/pandaboard/std.pandaboard4
-rw-r--r--sys/arm/ti/ti_adc.c20
-rw-r--r--sys/arm/ti/ti_cpuid.c10
-rw-r--r--sys/arm/ti/ti_cpuid.h11
-rw-r--r--sys/arm/ti/ti_edma3.c1
-rw-r--r--sys/arm/ti/ti_gpio.c14
-rw-r--r--sys/arm/ti/ti_hwmods.c1
-rw-r--r--sys/arm/ti/ti_machdep.c32
-rw-r--r--sys/arm/ti/ti_mbox.c1
-rw-r--r--sys/arm/ti/ti_pinmux.c46
-rw-r--r--sys/arm/ti/ti_pruss.c1
-rw-r--r--sys/arm/ti/ti_scm.c3
-rw-r--r--sys/arm/ti/ti_sdhci.c5
-rw-r--r--sys/arm/ti/ti_sdma.c1
-rw-r--r--sys/arm/ti/ti_spi.c1
-rw-r--r--sys/arm/ti/ti_wdt.c1
-rw-r--r--sys/arm/ti/usb/omap_ehci.c18
-rw-r--r--sys/arm/ti/usb/omap_host.c1
-rw-r--r--sys/arm/ti/usb/omap_tll.c1
-rw-r--r--sys/arm/versatile/pl050.c1
-rw-r--r--sys/arm/versatile/sp804.c5
-rw-r--r--sys/arm/versatile/versatile_clcd.c1
-rw-r--r--sys/arm/versatile/versatile_common.c3
-rw-r--r--sys/arm/versatile/versatile_machdep.c2
-rw-r--r--sys/arm/versatile/versatile_pci.c1
-rw-r--r--sys/arm/versatile/versatile_sic.c1
-rw-r--r--sys/arm/versatile/versatile_timer.c1
-rw-r--r--sys/arm/xilinx/zy7_devcfg.c1
-rw-r--r--sys/arm/xilinx/zy7_ehci.c1
-rw-r--r--sys/arm/xilinx/zy7_gpio.c1
-rw-r--r--sys/arm/xilinx/zy7_machdep.c25
-rw-r--r--sys/arm/xilinx/zy7_slcr.c5
-rw-r--r--sys/arm64/conf/GENERIC1
-rw-r--r--sys/boot/common/commands.c6
-rw-r--r--sys/boot/common/dev_net.c9
-rw-r--r--sys/boot/common/install.c20
-rw-r--r--sys/boot/common/md.c11
-rw-r--r--sys/boot/efi/libefi/efinet.c4
-rw-r--r--sys/boot/efi/libefi/efipart.c4
-rw-r--r--sys/boot/fdt/dts/arm/sun7i-a20-hdmi.dtsi22
-rw-r--r--sys/boot/fdt/dts/powerpc/p2041rdb.dts41
-rw-r--r--sys/boot/fdt/dts/powerpc/p2041si.dtsi48
-rw-r--r--sys/boot/fdt/dts/powerpc/p3041ds.dts41
-rw-r--r--sys/boot/fdt/dts/powerpc/p3041si.dtsi54
-rw-r--r--sys/boot/fdt/dts/powerpc/p5020ds.dts41
-rw-r--r--sys/boot/fdt/dts/powerpc/p5020si.dtsi48
-rw-r--r--sys/boot/forth/loader.conf1
-rw-r--r--sys/boot/i386/libfirewire/firewire.c4
-rw-r--r--sys/boot/i386/libi386/bioscd.c7
-rw-r--r--sys/boot/i386/libi386/biosdisk.c7
-rw-r--r--sys/boot/i386/libi386/pxe.c3
-rw-r--r--sys/boot/mips/beri/loader/beri_disk_cfi.c4
-rw-r--r--sys/boot/mips/beri/loader/beri_disk_sdcard.c6
-rw-r--r--sys/boot/pc98/libpc98/bioscd.c7
-rw-r--r--sys/boot/pc98/libpc98/biosdisk.c7
-rw-r--r--sys/boot/uboot/lib/disk.c7
-rw-r--r--sys/boot/usb/storage/umass_loader.c4
-rw-r--r--sys/boot/userboot/userboot/host.c4
-rw-r--r--sys/boot/userboot/userboot/userboot_disk.c7
-rw-r--r--sys/boot/zfs/zfs.c7
-rw-r--r--sys/boot/zfs/zfsimpl.c4
-rw-r--r--sys/cam/scsi/scsi_xpt.c4
-rw-r--r--sys/cddl/compat/opensolaris/sys/vnode.h3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c90
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil_impl.h5
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c37
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c8
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c121
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c15
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c50
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c4
-rw-r--r--sys/conf/Makefile.mips2
-rw-r--r--sys/conf/NOTES2
-rw-r--r--sys/conf/files49
-rw-r--r--sys/conf/files.amd644
-rw-r--r--sys/conf/files.arm641
-rw-r--r--sys/conf/files.i3864
-rw-r--r--sys/conf/kern.pre.mk2
-rw-r--r--sys/conf/newvers.sh33
-rw-r--r--sys/conf/options5
-rw-r--r--sys/conf/options.riscv2
-rw-r--r--sys/contrib/ncsw/inc/xx_ext.h5
-rw-r--r--sys/contrib/ncsw/user/env/xx.c114
-rw-r--r--sys/contrib/vchiq/interface/compat/vchi_bsd.c1
-rw-r--r--sys/dev/acpi_support/acpi_hp.c351
-rw-r--r--sys/dev/bhnd/bcma/bcma.c6
-rw-r--r--sys/dev/bhnd/bcma/bcma_dmp.h2
-rw-r--r--sys/dev/bnxt/bnxt.h568
-rw-r--r--sys/dev/bnxt/bnxt_hwrm.c1485
-rw-r--r--sys/dev/bnxt/bnxt_hwrm.h102
-rw-r--r--sys/dev/bnxt/bnxt_ioctl.h192
-rw-r--r--sys/dev/bnxt/bnxt_sysctl.c618
-rw-r--r--sys/dev/bnxt/bnxt_sysctl.h41
-rw-r--r--sys/dev/bnxt/bnxt_txrx.c641
-rwxr-xr-xsys/dev/bnxt/convert_hsi.pl356
-rw-r--r--sys/dev/bnxt/hsi_struct_def.h17576
-rw-r--r--sys/dev/bnxt/if_bnxt.c2360
-rw-r--r--sys/dev/cpuctl/cpuctl.c2
-rw-r--r--sys/dev/dme/if_dme.c1061
-rw-r--r--sys/dev/dme/if_dmereg.h137
-rw-r--r--sys/dev/dme/if_dmevar.h39
-rw-r--r--sys/dev/dpaa/bman_fdt.c38
-rw-r--r--sys/dev/dpaa/dpaa.c184
-rw-r--r--sys/dev/dpaa/fman.c32
-rw-r--r--sys/dev/dpaa/fman.h3
-rw-r--r--sys/dev/dpaa/if_dtsec.c4
-rw-r--r--sys/dev/dpaa/if_dtsec_fdt.c45
-rw-r--r--sys/dev/dpaa/if_dtsec_rm.c2
-rw-r--r--sys/dev/dpaa/qman_fdt.c83
-rw-r--r--sys/dev/drm2/drmP.h207
-rw-r--r--sys/dev/drm2/drm_memory.c4
-rw-r--r--sys/dev/drm2/drm_os_freebsd.c2
-rw-r--r--sys/dev/drm2/drm_os_freebsd.h2
-rw-r--r--sys/dev/drm2/ttm/ttm_bo_util.c3
-rw-r--r--sys/dev/e1000/if_em.c14
-rw-r--r--sys/dev/etherswitch/e6000sw/e6060sw.c703
-rw-r--r--sys/dev/etherswitch/infineon/adm6996fc.c858
-rw-r--r--sys/dev/etherswitch/ip17x/ip175c.c7
-rw-r--r--sys/dev/etherswitch/ip17x/ip175c.h3
-rw-r--r--sys/dev/etherswitch/rtl8366/rtl8366rb.c364
-rw-r--r--sys/dev/etherswitch/rtl8366/rtl8366rbvar.h193
-rw-r--r--sys/dev/fdt/fdt_arm_platform.c3
-rw-r--r--sys/dev/fdt/fdt_common.c18
-rw-r--r--sys/dev/fdt/fdt_common.h1
-rw-r--r--sys/dev/fdt/fdt_powerpc.c2
-rw-r--r--sys/dev/gpio/gpiobus.c3
-rw-r--r--sys/dev/gpio/gpiopower.c137
-rw-r--r--sys/dev/hyperv/pcib/vmbus_pcib.c1791
-rw-r--r--sys/dev/hyperv/utilities/hv_snapshot.c1061
-rw-r--r--sys/dev/hyperv/utilities/hv_snapshot.h56
-rw-r--r--sys/dev/hyperv/vmbus/vmbus.c246
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_if.m6
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_var.h10
-rw-r--r--sys/dev/ic/ns16550.h10
-rw-r--r--sys/dev/iicbus/iicsmb.c18
-rw-r--r--sys/dev/intpm/intpm.c39
-rw-r--r--sys/dev/ioat/ioat.c9
-rw-r--r--sys/dev/iwm/if_iwm.c40
-rw-r--r--sys/dev/kbdmux/kbdmux.c79
-rw-r--r--sys/dev/rtwn/if_rtwn_tx.h2
-rw-r--r--sys/dev/rtwn/pci/rtwn_pci_attach.c19
-rw-r--r--sys/dev/rtwn/pci/rtwn_pci_rx.c52
-rw-r--r--sys/dev/rtwn/pci/rtwn_pci_tx.c33
-rw-r--r--sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c14
-rw-r--r--sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c1
-rw-r--r--sys/dev/rtwn/rtl8812a/r12a_rom.c19
-rw-r--r--sys/dev/rtwn/rtl8812a/r12a_var.h18
-rw-r--r--sys/dev/rtwn/rtl8812a/usb/r12au_attach.c1
-rw-r--r--sys/dev/rtwn/rtl8821a/usb/r21au_attach.c1
-rw-r--r--sys/dev/rtwn/usb/rtwn_usb_rx.c3
-rw-r--r--sys/dev/smbus/smb.c10
-rw-r--r--sys/dev/smbus/smb.h7
-rw-r--r--sys/dev/uart/uart_bus_fdt.c2
-rw-r--r--sys/dev/uart/uart_core.c7
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c43
-rw-r--r--sys/dev/usb/controller/dwc_otg.c27
-rw-r--r--sys/dev/usb/controller/dwc_otg.h7
-rw-r--r--sys/dev/usb/controller/dwc_otg_fdt.c3
-rw-r--r--sys/dev/usb/controller/dwc_otg_fdt.h1
-rw-r--r--sys/dev/usb/net/if_smsc.c10
-rw-r--r--sys/dev/virtio/console/virtio_console.c5
-rw-r--r--sys/fs/autofs/autofs.c2
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c26
-rw-r--r--sys/fs/tmpfs/tmpfs_subr.c9
-rw-r--r--sys/geom/mirror/g_mirror.c66
-rw-r--r--sys/geom/mirror/g_mirror.h1
-rw-r--r--sys/geom/multipath/g_multipath.c2
-rw-r--r--sys/gnu/dts/include/dt-bindings/dma/jz4780-dma.h49
-rw-r--r--sys/gnu/dts/include/dt-bindings/net/rfkill-regulator.h23
-rw-r--r--sys/gnu/dts/mips/ingenic/canna.dts42
-rw-r--r--sys/gnu/dts/mips/ingenic/ci20.dts395
-rw-r--r--sys/gnu/dts/mips/ingenic/jz4780.dtsi768
-rw-r--r--sys/gnu/dts/mips/ingenic/x1000.dtsi420
-rw-r--r--sys/i386/i386/trap.c16
-rw-r--r--sys/kern/kern_exec.c2
-rw-r--r--sys/kern/kern_sendfile.c93
-rw-r--r--sys/kern/kern_umtx.c2
-rw-r--r--sys/kern/sched_4bsd.c67
-rw-r--r--sys/kern/subr_bus.c39
-rw-r--r--sys/kern/uipc_mqueue.c11
-rw-r--r--sys/kern/uipc_shm.c9
-rw-r--r--sys/kern/vfs_bio.c19
-rw-r--r--sys/kern/vfs_cache.c17
-rw-r--r--sys/kern/vfs_export.c4
-rw-r--r--sys/kern/vfs_mount.c44
-rw-r--r--sys/mips/atheros/ar531x/files.ar531513
-rw-r--r--sys/mips/atheros/ar531x/if_are.c104
-rw-r--r--sys/mips/atheros/ar531x/if_arereg.h31
-rw-r--r--sys/mips/include/cpufunc.h10
-rw-r--r--sys/mips/include/cpuregs.h8
-rw-r--r--sys/mips/include/locore.h3
-rw-r--r--sys/mips/include/param.h39
-rw-r--r--sys/mips/mediatek/mtk_soc.c2
-rw-r--r--sys/mips/mips/cpu.c14
-rw-r--r--sys/mips/mips/pmap.c14
-rw-r--r--sys/modules/Makefile1
-rw-r--r--sys/modules/bnxt/Makefile14
-rw-r--r--sys/modules/dtrace/dtrace/Makefile4
-rw-r--r--sys/modules/hyperv/pcib/Makefile12
-rw-r--r--sys/modules/hyperv/utilities/Makefile2
-rw-r--r--sys/modules/hyperv/vmbus/Makefile2
-rw-r--r--sys/modules/kbdmux/Makefile3
-rw-r--r--sys/modules/rpi_ft5406/Makefile2
-rw-r--r--sys/net/iflib.c136
-rw-r--r--sys/net/rtsock.c42
-rw-r--r--sys/net80211/_ieee80211.h67
-rw-r--r--sys/net80211/ieee80211_adhoc.c28
-rw-r--r--sys/net80211/ieee80211_crypto.c49
-rw-r--r--sys/net80211/ieee80211_crypto.h7
-rw-r--r--sys/net80211/ieee80211_crypto_ccmp.c40
-rw-r--r--sys/net80211/ieee80211_crypto_tkip.c77
-rw-r--r--sys/net80211/ieee80211_hostap.c45
-rw-r--r--sys/net80211/ieee80211_ioctl.c20
-rw-r--r--sys/net80211/ieee80211_node.c17
-rw-r--r--sys/net80211/ieee80211_output.c38
-rw-r--r--sys/net80211/ieee80211_scan_sta.c3
-rw-r--r--sys/net80211/ieee80211_sta.c67
-rw-r--r--sys/net80211/ieee80211_tdma.c7
-rw-r--r--sys/net80211/ieee80211_var.h64
-rw-r--r--sys/net80211/ieee80211_wds.c21
-rw-r--r--sys/netgraph/ng_l2tp.c10
-rw-r--r--sys/netinet/tcp_input.c3
-rw-r--r--sys/netinet/tcp_stacks/fastpath.c3
-rw-r--r--sys/netinet/tcp_subr.c5
-rw-r--r--sys/netinet/tcp_timewait.c1
-rw-r--r--sys/powerpc/booke/pmap.c41
-rw-r--r--sys/powerpc/conf/MPC85XX3
-rw-r--r--sys/powerpc/conf/MPC85XXSPE4
-rw-r--r--sys/powerpc/conf/dpaa/files.dpaa2
-rw-r--r--sys/powerpc/include/pmap.h4
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.h2
-rw-r--r--sys/powerpc/mpc85xx/platform_mpc85xx.c4
-rw-r--r--sys/powerpc/mpc85xx/qoriq_gpio.c4
-rw-r--r--sys/riscv/conf/GENERIC2
-rw-r--r--sys/riscv/include/fpe.h (renamed from sys/arm/rockchip/rk30xx_common.c)45
-rw-r--r--sys/riscv/include/pcb.h25
-rw-r--r--sys/riscv/include/reg.h5
-rw-r--r--sys/riscv/include/riscvreg.h8
-rw-r--r--sys/riscv/riscv/genassym.c2
-rw-r--r--sys/riscv/riscv/machdep.c82
-rw-r--r--sys/riscv/riscv/mp_machdep.c7
-rw-r--r--sys/riscv/riscv/pmap.c2
-rw-r--r--sys/riscv/riscv/swtch.S167
-rw-r--r--sys/riscv/riscv/trap.c13
-rw-r--r--sys/riscv/riscv/vm_machdep.c4
-rw-r--r--sys/sys/kerneldump.h4
-rw-r--r--sys/sys/queue.h39
-rw-r--r--sys/sys/sf_buf.h1
-rw-r--r--sys/sys/socket.h1
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c20
-rw-r--r--sys/vm/swap_pager.c5
-rw-r--r--sys/vm/vm_fault.c83
-rw-r--r--sys/vm/vm_mmap.c3
-rw-r--r--sys/vm/vm_object.c39
-rw-r--r--sys/vm/vm_object.h8
-rw-r--r--sys/vm/vm_page.c364
-rw-r--r--sys/vm/vm_page.h6
-rw-r--r--sys/vm/vm_reserv.c39
-rw-r--r--sys/vm/vm_reserv.h1
-rw-r--r--sys/vm/vnode_pager.c49
423 files changed, 35362 insertions, 2952 deletions
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 024c1b34a6cc..aa98fbd381e0 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -761,11 +761,11 @@ trap_fatal(frame, eva)
#endif
if (type == T_PAGEFLT) {
printf("fault virtual address = 0x%lx\n", eva);
- printf("fault code = %s %s %s%s, %s\n",
+ printf("fault code = %s %s %s, %s\n",
code & PGEX_U ? "user" : "supervisor",
code & PGEX_W ? "write" : "read",
code & PGEX_I ? "instruction" : "data",
- code & PGEX_RSV ? " rsv" : "",
+ code & PGEX_RSV ? "reserved bits in PTE" :
code & PGEX_P ? "protection violation" : "page not present");
}
printf("instruction pointer = 0x%lx:0x%lx\n",
diff --git a/sys/arm/allwinner/a10/a10_intc.c b/sys/arm/allwinner/a10/a10_intc.c
index fd6c4073fb34..996d28a950da 100644
--- a/sys/arm/allwinner/a10/a10_intc.c
+++ b/sys/arm/allwinner/a10/a10_intc.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c
index 1ea55357c140..85c26504058d 100644
--- a/sys/arm/allwinner/a10_gpio.c
+++ b/sys/arm/allwinner/a10_gpio.c
@@ -44,11 +44,10 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
-#include <dev/fdt/fdt_pinctrl.h>
#include <dev/gpio/gpiobusvar.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/fdt/fdt_pinctrl.h>
#include <arm/allwinner/aw_machdep.h>
#include <arm/allwinner/allwinner_pinctrl.h>
diff --git a/sys/arm/allwinner/a10_hdmi.c b/sys/arm/allwinner/a10_hdmi.c
index 1b7cbd2145ac..96613719e2e8 100644
--- a/sys/arm/allwinner/a10_hdmi.c
+++ b/sys/arm/allwinner/a10_hdmi.c
@@ -581,7 +581,7 @@ a10hdmi_get_tcon_config(struct a10hdmi_softc *sc, int *div, int *dbl)
/* Detect LCD CH1 special clock using a 1X or 2X source */
/* XXX */
pname = clk_get_name(clk_lcd_parent);
- if (strcmp(pname, "pll3-1x") == 0 || strcmp(pname, "pll7-1x") == 0)
+ if (strcmp(pname, "pll3") == 0 || strcmp(pname, "pll7") == 0)
*dbl = 0;
else
*dbl = 1;
diff --git a/sys/arm/allwinner/a10_mmc.c b/sys/arm/allwinner/a10_mmc.c
index a5eecb80de15..3c94bba9f125 100644
--- a/sys/arm/allwinner/a10_mmc.c
+++ b/sys/arm/allwinner/a10_mmc.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#define A10_MMC_DMA_SEGS ((MAXPHYS / PAGE_SIZE) + 1)
#define A10_MMC_DMA_MAX_SIZE 0x2000
#define A10_MMC_DMA_FTRGLEVEL 0x20070008
+#define A10_MMC_RESET_RETRY 1000
#define CARD_ID_FREQUENCY 400000
@@ -229,7 +230,7 @@ a10_mmc_attach(device_t dev)
bus_width = 4;
sc->a10_host.f_min = 400000;
- sc->a10_host.f_max = 50000000;
+ sc->a10_host.f_max = 52000000;
sc->a10_host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
sc->a10_host.mode = mode_sd;
sc->a10_host.caps = MMC_CAP_HSPEED;
@@ -449,11 +450,27 @@ a10_mmc_req_done(struct a10_mmc_softc *sc)
{
struct mmc_command *cmd;
struct mmc_request *req;
+ uint32_t val, mask;
+ int retry;
cmd = sc->a10_req->cmd;
if (cmd->error != MMC_ERR_NONE) {
- /* Reset the controller. */
- a10_mmc_reset(sc);
+ /* Reset the FIFO and DMA engines. */
+ mask = A10_MMC_CTRL_FIFO_RST | A10_MMC_CTRL_DMA_RST;
+ val = A10_MMC_READ_4(sc, A10_MMC_GCTL);
+ A10_MMC_WRITE_4(sc, A10_MMC_GCTL, val | mask);
+
+ retry = A10_MMC_RESET_RETRY;
+ while (--retry > 0) {
+ val = A10_MMC_READ_4(sc, A10_MMC_GCTL);
+ if ((val & mask) == 0)
+ break;
+ DELAY(10);
+ }
+ if (retry == 0)
+ device_printf(sc->a10_dev,
+ "timeout resetting DMA/FIFO\n");
+ a10_mmc_update_clock(sc, 1);
}
req = sc->a10_req;
diff --git a/sys/arm/allwinner/a10_sramc.c b/sys/arm/allwinner/a10_sramc.c
index 22ba1f7c4adf..ea9654518e5f 100644
--- a/sys/arm/allwinner/a10_sramc.c
+++ b/sys/arm/allwinner/a10_sramc.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <machine/frame.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/allwinner/a20/a20_cpu_cfg.c b/sys/arm/allwinner/a20/a20_cpu_cfg.c
index a0bdb5a0b46e..3fe53349b4dc 100644
--- a/sys/arm/allwinner/a20/a20_cpu_cfg.c
+++ b/sys/arm/allwinner/a20/a20_cpu_cfg.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/allwinner/aw_ccu.c b/sys/arm/allwinner/aw_ccu.c
index 52d9cdacbfe4..fca85b85bd5c 100644
--- a/sys/arm/allwinner/aw_ccu.c
+++ b/sys/arm/allwinner/aw_ccu.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <dev/fdt/simplebus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -195,7 +194,7 @@ aw_ccu_search_compatible(void)
root = OF_finddevice("/");
for (compat = compat_data; compat->ocd_str != NULL; compat++)
- if (fdt_is_compatible(root, compat->ocd_str))
+ if (ofw_bus_node_is_compatible(root, compat->ocd_str))
break;
return (compat);
diff --git a/sys/arm/allwinner/aw_cir.c b/sys/arm/allwinner/aw_cir.c
index 926109a4d123..2c6c275b1fbf 100644
--- a/sys/arm/allwinner/aw_cir.c
+++ b/sys/arm/allwinner/aw_cir.c
@@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/allwinner/aw_machdep.c b/sys/arm/allwinner/aw_machdep.c
index 73b1e58f9491..d9effb8eec91 100644
--- a/sys/arm/allwinner/aw_machdep.c
+++ b/sys/arm/allwinner/aw_machdep.c
@@ -48,8 +48,6 @@ __FBSDID("$FreeBSD$");
#include <machine/machdep.h>
#include <machine/platformvar.h>
-#include <dev/fdt/fdt_common.h>
-
#include <arm/allwinner/aw_mp.h>
#include <arm/allwinner/aw_wdog.h>
#include <arm/allwinner/aw_machdep.h>
diff --git a/sys/arm/allwinner/aw_nmi.c b/sys/arm/allwinner/aw_nmi.c
index 67be72d6b056..86c122f5300a 100644
--- a/sys/arm/allwinner/aw_nmi.c
+++ b/sys/arm/allwinner/aw_nmi.c
@@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/fdt/fdt_intr.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/allwinner/aw_thermal.c b/sys/arm/allwinner/aw_thermal.c
index 12146afd968d..5143cda95fb3 100644
--- a/sys/arm/allwinner/aw_thermal.c
+++ b/sys/arm/allwinner/aw_thermal.c
@@ -109,10 +109,13 @@ __FBSDID("$FreeBSD$");
#define H3_ADC_ACQUIRE_TIME 0x3f
#define H3_FILTER 0x6
#define H3_INTC 0x191000
-#define H3_TEMP_BASE 1794000
+#define H3_TEMP_BASE 217
#define H3_TEMP_MUL 1000
-#define H3_TEMP_DIV -8253
+#define H3_TEMP_DIV 8253
+#define H3_TEMP_MINUS 1794000
#define H3_CLK_RATE 4000000
+#define H3_INIT_ALARM 90 /* degC */
+#define H3_INIT_SHUT 105 /* degC */
#define TEMP_C_TO_K 273
#define SENSOR_ENABLE_ALL (SENSOR0_EN|SENSOR1_EN|SENSOR2_EN)
@@ -131,6 +134,8 @@ TUNABLE_INT("hw.aw_thermal.throttle_enable", &aw_thermal_throttle_enable);
struct aw_thermal_sensor {
const char *name;
const char *desc;
+ int init_alarm;
+ int init_shut;
};
struct aw_thermal_config {
@@ -142,6 +147,7 @@ struct aw_thermal_config {
uint32_t filter;
uint32_t intc;
int (*to_temp)(uint32_t);
+ uint32_t (*to_reg)(int);
int temp_base;
int temp_mul;
int temp_div;
@@ -177,9 +183,7 @@ static const struct aw_thermal_config a83t_config = {
.filter = A83T_FILTER,
.intc = A83T_INTC,
.to_temp = a83t_to_temp,
- .calib0 = 1,
.calib0_mask = 0xffffffff,
- .calib1 = 1,
.calib1_mask = 0xffffffff,
};
@@ -215,7 +219,13 @@ static const struct aw_thermal_config a64_config = {
static int
h3_to_temp(uint32_t val)
{
- return (((int)(val * H3_TEMP_MUL) - H3_TEMP_BASE) / H3_TEMP_DIV);
+ return (H3_TEMP_BASE - ((val * H3_TEMP_MUL) / H3_TEMP_DIV));
+}
+
+static uint32_t
+h3_to_reg(int val)
+{
+ return ((H3_TEMP_MINUS - (val * H3_TEMP_DIV)) / H3_TEMP_MUL);
}
static const struct aw_thermal_config h3_config = {
@@ -224,6 +234,8 @@ static const struct aw_thermal_config h3_config = {
[0] = {
.name = "cpu",
.desc = "CPU temperature",
+ .init_alarm = H3_INIT_ALARM,
+ .init_shut = H3_INIT_SHUT,
},
},
.clk_rate = H3_CLK_RATE,
@@ -231,7 +243,7 @@ static const struct aw_thermal_config h3_config = {
.filter = H3_FILTER,
.intc = H3_INTC,
.to_temp = h3_to_temp,
- .calib0 = 1,
+ .to_reg = h3_to_reg,
.calib0_mask = 0xfff,
};
@@ -272,7 +284,7 @@ aw_thermal_init(struct aw_thermal_softc *sc)
uint32_t calib0, calib1;
int error;
- if (sc->conf->calib0 != 0 || sc->conf->calib1 != 0) {
+ if (sc->conf->calib0_mask != 0 || sc->conf->calib1_mask != 0) {
/* Read calibration settings from SRAM */
error = aw_sid_read_tscalib(&calib0, &calib1);
if (error != 0)
@@ -282,9 +294,9 @@ aw_thermal_init(struct aw_thermal_softc *sc)
calib1 &= sc->conf->calib1_mask;
/* Write calibration settings to thermal controller */
- if (sc->conf->calib0 != 0 && calib0 != 0)
+ if (calib0 != 0)
WR4(sc, THS_CALIB0, calib0);
- if (sc->conf->calib1 != 0 && calib1 != 0)
+ if (calib1 != 0)
WR4(sc, THS_CALIB1, calib1);
}
@@ -313,7 +325,7 @@ aw_thermal_gettemp(struct aw_thermal_softc *sc, int sensor)
val = RD4(sc, THS_DATA0 + (sensor * 4));
- return (sc->conf->to_temp(val) + TEMP_C_TO_K);
+ return (sc->conf->to_temp(val));
}
static int
@@ -324,7 +336,18 @@ aw_thermal_getshut(struct aw_thermal_softc *sc, int sensor)
val = RD4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4));
val = (val >> SHUT_T_HOT_SHIFT) & SHUT_T_HOT_MASK;
- return (sc->conf->to_temp(val) + TEMP_C_TO_K);
+ return (sc->conf->to_temp(val));
+}
+
+static void
+aw_thermal_setshut(struct aw_thermal_softc *sc, int sensor, int temp)
+{
+ uint32_t val;
+
+ val = RD4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4));
+ val &= ~(SHUT_T_HOT_MASK << SHUT_T_HOT_SHIFT);
+ val |= (sc->conf->to_reg(temp) << SHUT_T_HOT_SHIFT);
+ WR4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4), val);
}
static int
@@ -335,7 +358,7 @@ aw_thermal_gethyst(struct aw_thermal_softc *sc, int sensor)
val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4));
val = (val >> ALARM_T_HYST_SHIFT) & ALARM_T_HYST_MASK;
- return (sc->conf->to_temp(val) + TEMP_C_TO_K);
+ return (sc->conf->to_temp(val));
}
static int
@@ -346,7 +369,18 @@ aw_thermal_getalarm(struct aw_thermal_softc *sc, int sensor)
val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4));
val = (val >> ALARM_T_HOT_SHIFT) & ALARM_T_HOT_MASK;
- return (sc->conf->to_temp(val) + TEMP_C_TO_K);
+ return (sc->conf->to_temp(val));
+}
+
+static void
+aw_thermal_setalarm(struct aw_thermal_softc *sc, int sensor, int temp)
+{
+ uint32_t val;
+
+ val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4));
+ val &= ~(ALARM_T_HOT_MASK << ALARM_T_HOT_SHIFT);
+ val |= (sc->conf->to_reg(temp) << ALARM_T_HOT_SHIFT);
+ WR4(sc, THS_ALARM0_CTRL + (sensor * 4), val);
}
static int
@@ -358,7 +392,7 @@ aw_thermal_sysctl(SYSCTL_HANDLER_ARGS)
sc = arg1;
sensor = arg2;
- val = aw_thermal_gettemp(sc, sensor);
+ val = aw_thermal_gettemp(sc, sensor) + TEMP_C_TO_K;
return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
}
@@ -514,6 +548,15 @@ aw_thermal_attach(device_t dev)
goto fail;
}
+ for (i = 0; i < sc->conf->nsensors; i++) {
+ if (sc->conf->sensors[i].init_alarm > 0)
+ aw_thermal_setalarm(sc, i,
+ sc->conf->sensors[i].init_alarm);
+ if (sc->conf->sensors[i].init_shut > 0)
+ aw_thermal_setshut(sc, i,
+ sc->conf->sensors[i].init_shut);
+ }
+
if (aw_thermal_init(sc) != 0)
goto fail;
@@ -529,9 +572,9 @@ aw_thermal_attach(device_t dev)
for (i = 0; i < sc->conf->nsensors; i++) {
device_printf(dev,
"#%d: alarm %dC hyst %dC shut %dC\n", i,
- aw_thermal_getalarm(sc, i) - TEMP_C_TO_K,
- aw_thermal_gethyst(sc, i) - TEMP_C_TO_K,
- aw_thermal_getshut(sc, i) - TEMP_C_TO_K);
+ aw_thermal_getalarm(sc, i),
+ aw_thermal_gethyst(sc, i),
+ aw_thermal_getshut(sc, i));
}
sc->cf_pre_tag = EVENTHANDLER_REGISTER(cpufreq_pre_change,
diff --git a/sys/arm/allwinner/aw_ts.c b/sys/arm/allwinner/aw_ts.c
index e010ac469b01..2963fb84ce6b 100644
--- a/sys/arm/allwinner/aw_ts.c
+++ b/sys/arm/allwinner/aw_ts.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/allwinner/aw_wdog.c b/sys/arm/allwinner/aw_wdog.c
index 4dcefd432b64..ca1ac0d98a79 100644
--- a/sys/arm/allwinner/aw_wdog.c
+++ b/sys/arm/allwinner/aw_wdog.c
@@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/rman.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/allwinner/clk/aw_gate.c b/sys/arm/allwinner/clk/aw_gate.c
index f26b7c2d1b94..078a5e8031f5 100644
--- a/sys/arm/allwinner/clk/aw_gate.c
+++ b/sys/arm/allwinner/clk/aw_gate.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/ofw_subr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/extres/clk/clk_gate.h>
diff --git a/sys/arm/allwinner/clk/aw_mmcclk.c b/sys/arm/allwinner/clk/aw_mmcclk.c
index 52ed231a952a..44377a8ced75 100644
--- a/sys/arm/allwinner/clk/aw_mmcclk.c
+++ b/sys/arm/allwinner/clk/aw_mmcclk.c
@@ -185,7 +185,7 @@ aw_mmcclk_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
ophase = 0;
phase = 5;
n = 2;
- } else if (*fout <= 50000000) {
+ } else if (*fout <= 52000000) {
parent_idx = CLK_SRC_SEL_PLL6;
ophase = 3;
phase = 5;
diff --git a/sys/arm/allwinner/clk/aw_pll.c b/sys/arm/allwinner/clk/aw_pll.c
index ab12dfa94dea..6d8226399c5d 100644
--- a/sys/arm/allwinner/clk/aw_pll.c
+++ b/sys/arm/allwinner/clk/aw_pll.c
@@ -180,9 +180,6 @@ __FBSDID("$FreeBSD$");
#define H3_PLL2_PRE_DIV (0x1f << 0)
#define H3_PLL2_PRE_DIV_SHIFT 0
-#define CLKID_A10_PLL3_1X 0
-#define CLKID_A10_PLL3_2X 1
-
#define CLKID_A10_PLL5_DDR 0
#define CLKID_A10_PLL5_OTHER 1
@@ -476,9 +473,6 @@ a10_pll3_recalc(struct aw_pll_sc *sc, uint64_t *freq)
*freq = 297000000;
}
- if (sc->id == CLKID_A10_PLL3_2X)
- *freq *= 2;
-
return (0);
}
@@ -489,14 +483,10 @@ a10_pll3_set_freq(struct aw_pll_sc *sc, uint64_t fin, uint64_t *fout,
uint32_t val, m, mode, func;
m = *fout / A10_PLL3_REF_FREQ;
- if (sc->id == CLKID_A10_PLL3_2X)
- m /= 2;
mode = A10_PLL3_MODE_SEL_INT;
func = 0;
*fout = m * A10_PLL3_REF_FREQ;
- if (sc->id == CLKID_A10_PLL3_2X)
- *fout *= 2;
DEVICE_LOCK(sc);
PLL_READ(sc, &val);
diff --git a/sys/arm/allwinner/if_emac.c b/sys/arm/allwinner/if_emac.c
index 097e4911037c..a500f7b64e76 100644
--- a/sys/arm/allwinner/if_emac.c
+++ b/sys/arm/allwinner/if_emac.c
@@ -69,7 +69,6 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
#include <net/bpfdesc.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/allwinner/timer.c b/sys/arm/allwinner/timer.c
index 2b4ec843d770..fec5f9a1eb31 100644
--- a/sys/arm/allwinner/timer.c
+++ b/sys/arm/allwinner/timer.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/machdep.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/altera/socfpga/socfpga_common.c b/sys/arm/altera/socfpga/socfpga_common.c
index 9944b90e8b52..12a2cc5c4716 100644
--- a/sys/arm/altera/socfpga/socfpga_common.c
+++ b/sys/arm/altera/socfpga/socfpga_common.c
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/kernel.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
@@ -47,7 +46,7 @@ __FBSDID("$FreeBSD$");
void
cpu_reset(void)
{
- uint32_t addr, paddr;
+ uint32_t paddr;
bus_addr_t vaddr;
phandle_t node;
@@ -58,9 +57,8 @@ cpu_reset(void)
if (node == -1)
goto end;
- if ((OF_getprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
- addr = fdt32_to_cpu(paddr);
- if (bus_space_map(fdtbus_bs_tag, addr, 0x8, 0, &vaddr) == 0) {
+ if ((OF_getencprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
+ if (bus_space_map(fdtbus_bs_tag, paddr, 0x8, 0, &vaddr) == 0) {
bus_space_write_4(fdtbus_bs_tag, vaddr,
RSTMGR_CTRL, CTRL_SWWARMRSTREQ);
}
@@ -69,24 +67,3 @@ cpu_reset(void)
end:
while (1);
}
-
-#ifndef INTRNG
-static int
-fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
- int *pol)
-{
-
- if (!fdt_is_compatible(node, "arm,gic"))
- return (ENXIO);
-
- *interrupt = fdt32_to_cpu(intr[0]);
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
- return (0);
-}
-
-fdt_pic_decode_t fdt_pic_table[] = {
- &fdt_pic_decode_ic,
- NULL
-};
-#endif
diff --git a/sys/arm/altera/socfpga/socfpga_gpio.c b/sys/arm/altera/socfpga/socfpga_gpio.c
index 0e71d18cc48a..2c064147414f 100644
--- a/sys/arm/altera/socfpga/socfpga_gpio.c
+++ b/sys/arm/altera/socfpga/socfpga_gpio.c
@@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/gpio.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/gpio/gpiobusvar.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/altera/socfpga/socfpga_manager.c b/sys/arm/altera/socfpga/socfpga_manager.c
index 3b63f79bbce5..33e4c74e4944 100644
--- a/sys/arm/altera/socfpga/socfpga_manager.c
+++ b/sys/arm/altera/socfpga/socfpga_manager.c
@@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/uio.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/altera/socfpga/socfpga_rstmgr.c b/sys/arm/altera/socfpga/socfpga_rstmgr.c
index 49db05ef4a1e..d5f773f5bfe5 100644
--- a/sys/arm/altera/socfpga/socfpga_rstmgr.c
+++ b/sys/arm/altera/socfpga/socfpga_rstmgr.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#include <sys/sysctl.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -84,7 +83,7 @@ enum {
static int
l3remap(struct rstmgr_softc *sc, int remap, int enable)
{
- uint32_t addr, paddr;
+ uint32_t paddr;
bus_addr_t vaddr;
phandle_t node;
int reg;
@@ -106,9 +105,8 @@ l3remap(struct rstmgr_softc *sc, int remap, int enable)
return (1);
}
- if ((OF_getprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
- addr = fdt32_to_cpu(paddr);
- if (bus_space_map(fdtbus_bs_tag, addr, 0x4, 0, &vaddr) == 0) {
+ if ((OF_getencprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
+ if (bus_space_map(fdtbus_bs_tag, paddr, 0x4, 0, &vaddr) == 0) {
bus_space_write_4(fdtbus_bs_tag, vaddr,
L3REGS_REMAP, reg);
return (0);
diff --git a/sys/arm/amlogic/aml8726/aml8726_ccm.c b/sys/arm/amlogic/aml8726/aml8726_ccm.c
index fb2c9a56f603..1c804c3ecda9 100644
--- a/sys/arm/amlogic/aml8726/aml8726_ccm.c
+++ b/sys/arm/amlogic/aml8726/aml8726_ccm.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_fb.c b/sys/arm/amlogic/aml8726/aml8726_fb.c
index 94d39065afcc..f2fc36de5caa 100644
--- a/sys/arm/amlogic/aml8726/aml8726_fb.c
+++ b/sys/arm/amlogic/aml8726/aml8726_fb.c
@@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/fdt.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_gpio.c b/sys/arm/amlogic/aml8726/aml8726_gpio.c
index afc6f5b7ce06..df26d91ee49a 100644
--- a/sys/arm/amlogic/aml8726/aml8726_gpio.c
+++ b/sys/arm/amlogic/aml8726/aml8726_gpio.c
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_i2c.c b/sys/arm/amlogic/aml8726/aml8726_i2c.c
index c47bb6eec800..7fd8d71cea43 100644
--- a/sys/arm/amlogic/aml8726/aml8726_i2c.c
+++ b/sys/arm/amlogic/aml8726/aml8726_i2c.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_mmc.c b/sys/arm/amlogic/aml8726/aml8726_mmc.c
index 3cc074442f62..b14dab005890 100644
--- a/sys/arm/amlogic/aml8726/aml8726_mmc.c
+++ b/sys/arm/amlogic/aml8726/aml8726_mmc.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/cpu.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_pic.c b/sys/arm/amlogic/aml8726/aml8726_pic.c
index 70257f747cd5..fd296ea63caa 100644
--- a/sys/arm/amlogic/aml8726/aml8726_pic.c
+++ b/sys/arm/amlogic/aml8726/aml8726_pic.c
@@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_pinctrl.c b/sys/arm/amlogic/aml8726/aml8726_pinctrl.c
index a71c25ae82fb..5465b1cbe04a 100644
--- a/sys/arm/amlogic/aml8726/aml8726_pinctrl.c
+++ b/sys/arm/amlogic/aml8726/aml8726_pinctrl.c
@@ -45,10 +45,9 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
-#include <dev/fdt/fdt_pinctrl.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/fdt/fdt_pinctrl.h>
#include <arm/amlogic/aml8726/aml8726_soc.h>
#include <arm/amlogic/aml8726/aml8726_pinctrl.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_rng.c b/sys/arm/amlogic/aml8726/aml8726_rng.c
index e3397aa117a6..9c38e3c8c06e 100644
--- a/sys/arm/amlogic/aml8726/aml8726_rng.c
+++ b/sys/arm/amlogic/aml8726/aml8726_rng.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_rtc.c b/sys/arm/amlogic/aml8726/aml8726_rtc.c
index 5af51ce4d34d..6ed8d7b77525 100644
--- a/sys/arm/amlogic/aml8726/aml8726_rtc.c
+++ b/sys/arm/amlogic/aml8726/aml8726_rtc.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/cpu.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c b/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c
index fc225352ed54..563eb5738013 100644
--- a/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c
+++ b/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/cpu.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_timer.c b/sys/arm/amlogic/aml8726/aml8726_timer.c
index 60617035ab03..2fa4db8f398e 100644
--- a/sys/arm/amlogic/aml8726/aml8726_timer.c
+++ b/sys/arm/amlogic/aml8726/aml8726_timer.c
@@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/cpu.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c b/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c
index 3a108e461543..3c6b796ead39 100644
--- a/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c
+++ b/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/cpu.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/aml8726_wdt.c b/sys/arm/amlogic/aml8726/aml8726_wdt.c
index cd78c9321bff..46bafccab95c 100644
--- a/sys/arm/amlogic/aml8726/aml8726_wdt.c
+++ b/sys/arm/amlogic/aml8726/aml8726_wdt.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/amlogic/aml8726/uart_dev_aml8726.c b/sys/arm/amlogic/aml8726/uart_dev_aml8726.c
index 5d21fb05569b..162e2eb2a9ac 100644
--- a/sys/arm/amlogic/aml8726/uart_dev_aml8726.c
+++ b/sys/arm/amlogic/aml8726/uart_dev_aml8726.c
@@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/cpu.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/annapurna/alpine/alpine_machdep.c b/sys/arm/annapurna/alpine/alpine_machdep.c
index 3d35834f1ca7..7f87c7d68984 100644
--- a/sys/arm/annapurna/alpine/alpine_machdep.c
+++ b/sys/arm/annapurna/alpine/alpine_machdep.c
@@ -45,8 +45,6 @@ __FBSDID("$FreeBSD$");
#include <machine/platform.h>
#include <machine/fdt.h>
-#include <dev/fdt/fdt_common.h>
-
#include "opt_ddb.h"
#include "opt_platform.h"
diff --git a/sys/arm/annapurna/alpine/alpine_machdep_mp.c b/sys/arm/annapurna/alpine/alpine_machdep_mp.c
index e48a1a3c5773..4ef2db1ba0f3 100644
--- a/sys/arm/annapurna/alpine/alpine_machdep_mp.c
+++ b/sys/arm/annapurna/alpine/alpine_machdep_mp.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu-v6.h>
#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_cpu.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -81,7 +82,7 @@ static boolean_t alpine_validate_cpu(u_int, phandle_t, u_int, pcell_t *);
static boolean_t
alpine_validate_cpu(u_int id, phandle_t child, u_int addr_cell, pcell_t *reg)
{
- return fdt_is_compatible(child, "arm,cortex-a15");
+ return ofw_bus_node_is_compatible(child, "arm,cortex-a15");
}
static int
diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c
index d91eee14ee44..e42a699986cc 100644
--- a/sys/arm/arm/generic_timer.c
+++ b/sys/arm/arm/generic_timer.c
@@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c
index 91ccf31635f5..ff97f5cde889 100644
--- a/sys/arm/arm/gic.c
+++ b/sys/arm/arm/gic.c
@@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/smp.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/fdt/fdt_intr.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -312,7 +311,7 @@ gic_decode_fdt(phandle_t iparent, pcell_t *intr, int *interrupt,
if (self == 0) {
for (ocd = compat_data; ocd->ocd_str != NULL; ocd++) {
- if (fdt_is_compatible(iparent, ocd->ocd_str)) {
+ if (ofw_bus_node_is_compatible(iparent, ocd->ocd_str)) {
self = iparent;
break;
}
diff --git a/sys/arm/arm/gic_fdt.c b/sys/arm/arm/gic_fdt.c
index 1ababce6e0fa..bd361c928c7b 100644
--- a/sys/arm/arm/gic_fdt.c
+++ b/sys/arm/arm/gic_fdt.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c
index 2dc71718e06f..25a9fcaebe15 100644
--- a/sys/arm/arm/mp_machdep.c
+++ b/sys/arm/arm/mp_machdep.c
@@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef CPU_MV_PJ4B
#include <arm/mv/mvwin.h>
-#include <dev/fdt/fdt_common.h>
#endif
extern struct pcpu __pcpu[];
diff --git a/sys/arm/arm/mpcore_timer.c b/sys/arm/arm/mpcore_timer.c
index 03f8e4bad6a8..e68a5e921baf 100644
--- a/sys/arm/arm/mpcore_timer.c
+++ b/sys/arm/arm/mpcore_timer.c
@@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/arm/pl190.c b/sys/arm/arm/pl190.c
index 8cd744e6c993..9817fa5ac17b 100644
--- a/sys/arm/arm/pl190.c
+++ b/sys/arm/arm/pl190.c
@@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/arm/pl310.c b/sys/arm/arm/pl310.c
index c269b47a8be3..18adabbd97c5 100644
--- a/sys/arm/arm/pl310.c
+++ b/sys/arm/arm/pl310.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/pl310.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c
index 5ac2fa8fd415..805a09d5f130 100644
--- a/sys/arm/arm/pmap-v6.c
+++ b/sys/arm/arm/pmap-v6.c
@@ -2739,31 +2739,25 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0,
/*
* Is given page managed?
*/
-static __inline boolean_t
+static __inline bool
is_managed(vm_paddr_t pa)
{
- vm_offset_t pgnum;
vm_page_t m;
- pgnum = atop(pa);
- if (pgnum >= first_page) {
- m = PHYS_TO_VM_PAGE(pa);
- if (m == NULL)
- return (FALSE);
- if ((m->oflags & VPO_UNMANAGED) == 0)
- return (TRUE);
- }
- return (FALSE);
+ m = PHYS_TO_VM_PAGE(pa);
+ if (m == NULL)
+ return (false);
+ return ((m->oflags & VPO_UNMANAGED) == 0);
}
-static __inline boolean_t
+static __inline bool
pte1_is_managed(pt1_entry_t pte1)
{
return (is_managed(pte1_pa(pte1)));
}
-static __inline boolean_t
+static __inline bool
pte2_is_managed(pt2_entry_t pte2)
{
@@ -6103,7 +6097,7 @@ pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa)
pt1_entry_t *pte1p, pte1;
pt2_entry_t *pte2p, pte2;
vm_paddr_t pa;
- boolean_t managed;
+ bool managed;
int val;
PMAP_LOCK(pmap);
@@ -6130,7 +6124,7 @@ retry:
if (pte2 & PTE2_A)
val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER;
} else {
- managed = FALSE;
+ managed = false;
val = 0;
}
if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) !=
diff --git a/sys/arm/arm/pmu.c b/sys/arm/arm/pmu.c
index c98d6c988740..ad785ca960ee 100644
--- a/sys/arm/arm/pmu.c
+++ b/sys/arm/arm/pmu.c
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <sys/pmc.h>
#include <sys/pmckern.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/at91/at91_aic.c b/sys/arm/at91/at91_aic.c
index 92d6eada203c..a6756da1dfa6 100644
--- a/sys/arm/at91/at91_aic.c
+++ b/sys/arm/at91/at91_aic.c
@@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91_aicreg.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/at91_cfata.c b/sys/arm/at91/at91_cfata.c
index 890029c13e32..8c6049d5b01c 100644
--- a/sys/arm/at91/at91_cfata.c
+++ b/sys/arm/at91/at91_cfata.c
@@ -114,7 +114,7 @@ at91_cfata_detach(device_t dev)
static struct resource *
ata_at91_alloc_resource(device_t dev, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct at91_cfata_softc *sc = device_get_softc(dev);
diff --git a/sys/arm/at91/at91_common.c b/sys/arm/at91/at91_common.c
index 696161f34001..8ef16fe7bc95 100644
--- a/sys/arm/at91/at91_common.c
+++ b/sys/arm/at91/at91_common.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <machine/fdt.h>
@@ -56,7 +57,7 @@ fdt_aic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
{
int offset;
- if (fdt_is_compatible(node, "atmel,at91rm9200-aic"))
+ if (ofw_bus_node_is_compatible(node, "atmel,at91rm9200-aic"))
offset = 0;
else
return (ENXIO);
diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c
index 2049fc74f937..477ce9dcc3c5 100644
--- a/sys/arm/at91/at91_mci.c
+++ b/sys/arm/at91/at91_mci.c
@@ -63,7 +63,6 @@ __FBSDID("$FreeBSD$");
#include <dev/mmc/mmcbrvar.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/at91_ohci_fdt.c b/sys/arm/at91/at91_ohci_fdt.c
index 51d9509fedcd..091cd98305f1 100644
--- a/sys/arm/at91/at91_ohci_fdt.c
+++ b/sys/arm/at91/at91_ohci_fdt.c
@@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91_pmcvar.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/at91/at91_pinctrl.c b/sys/arm/at91/at91_pinctrl.c
index 7ca379be9303..f2c3824f2d59 100644
--- a/sys/arm/at91/at91_pinctrl.c
+++ b/sys/arm/at91/at91_pinctrl.c
@@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91var.h>
#include <arm/at91/at91_piovar.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/fdt/fdt_pinctrl.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/at91/at91_pio.c b/sys/arm/at91/at91_pio.c
index 0d9bd46a4215..20f5002db2d7 100644
--- a/sys/arm/at91/at91_pio.c
+++ b/sys/arm/at91/at91_pio.c
@@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91_piovar.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/at91_pit.c b/sys/arm/at91/at91_pit.c
index 7f7890b01783..a48af8823919 100644
--- a/sys/arm/at91/at91_pit.c
+++ b/sys/arm/at91/at91_pit.c
@@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91_pitreg.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/at91_pmc.c b/sys/arm/at91/at91_pmc.c
index 3784bada9418..572bfa0de2be 100644
--- a/sys/arm/at91/at91_pmc.c
+++ b/sys/arm/at91/at91_pmc.c
@@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91_pmcvar.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/at91_rst.c b/sys/arm/at91/at91_rst.c
index 77ace5fbe613..48f781ac0533 100644
--- a/sys/arm/at91/at91_rst.c
+++ b/sys/arm/at91/at91_rst.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91board.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#define FDT_HACKS 1
diff --git a/sys/arm/at91/at91_sdramc.c b/sys/arm/at91/at91_sdramc.c
index 99787ba7a71d..3136db6a091e 100644
--- a/sys/arm/at91/at91_sdramc.c
+++ b/sys/arm/at91/at91_sdramc.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91_aicreg.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/at91_shdwc.c b/sys/arm/at91/at91_shdwc.c
index f3fa491dad8f..92d56440e765 100644
--- a/sys/arm/at91/at91_shdwc.c
+++ b/sys/arm/at91/at91_shdwc.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91_aicreg.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/at91_spi.c b/sys/arm/at91/at91_spi.c
index cdbc7b8e2986..bbe80ab1d36f 100644
--- a/sys/arm/at91/at91_spi.c
+++ b/sys/arm/at91/at91_spi.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <dev/spibus/spibusvar.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/at91_tcb.c b/sys/arm/at91/at91_tcb.c
index 42491ed74bd0..5db1d3c4f74e 100644
--- a/sys/arm/at91/at91_tcb.c
+++ b/sys/arm/at91/at91_tcb.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91_aicreg.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/at91_twi.c b/sys/arm/at91/at91_twi.c
index 28676fc7cd85..8549406c57c5 100644
--- a/sys/arm/at91/at91_twi.c
+++ b/sys/arm/at91/at91_twi.c
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include "iicbus_if.h"
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/at91_wdt.c b/sys/arm/at91/at91_wdt.c
index 95332025e2f7..dd0887dd905e 100644
--- a/sys/arm/at91/at91_wdt.c
+++ b/sys/arm/at91/at91_wdt.c
@@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/at91_wdtreg.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/if_ate.c b/sys/arm/at91/if_ate.c
index fdca46bf95fc..8f742048b078 100644
--- a/sys/arm/at91/if_ate.c
+++ b/sys/arm/at91/if_ate.c
@@ -77,7 +77,6 @@ __FBSDID("$FreeBSD$");
#include <arm/at91/if_atereg.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/at91/if_macb.c b/sys/arm/at91/if_macb.c
index c62184d2803b..f0709a3335a1 100644
--- a/sys/arm/at91/if_macb.c
+++ b/sys/arm/at91/if_macb.c
@@ -76,7 +76,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#endif
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
index ea4b6f604ee4..f20d5204828d 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
@@ -44,8 +44,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
-
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -1261,7 +1259,7 @@ bcm2835_cpufreq_identify(driver_t *driver, device_t parent)
root = OF_finddevice("/");
for (compat = compat_data; compat->ocd_str != NULL; compat++)
- if (fdt_is_compatible(root, compat->ocd_str))
+ if (ofw_bus_node_is_compatible(root, compat->ocd_str))
break;
if (compat->ocd_data == 0)
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_dma.c b/sys/arm/broadcom/bcm2835/bcm2835_dma.c
index 3b6c03201fa1..acb6e3afa97a 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_dma.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_dma.c
@@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
#include <sys/resource.h>
#include <sys/rman.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fb.c b/sys/arm/broadcom/bcm2835/bcm2835_fb.c
index 58caac2cd884..d8c25b5a6e80 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_fb.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_fb.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <dev/fb/fbreg.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/syscons/syscons.h>
@@ -474,15 +473,15 @@ bcmfb_configure(int flags)
if ((root != 0) &&
(display = fdt_find_compatible(root, "broadcom,bcm2835-fb", 1))) {
if (sc->width == 0) {
- if ((OF_getprop(display, "broadcom,width",
+ if ((OF_getencprop(display, "broadcom,width",
&cell, sizeof(cell))) > 0)
- sc->width = (int)fdt32_to_cpu(cell);
+ sc->width = cell;
}
if (sc->height == 0) {
- if ((OF_getprop(display, "broadcom,height",
+ if ((OF_getencprop(display, "broadcom,height",
&cell, sizeof(cell))) > 0)
- sc->height = (int)fdt32_to_cpu(cell);
+ sc->height = cell;
}
}
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c
index 04cc83a42c81..f26b5c19697c 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c b/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c
index 86432cfca4ad..026d4c574f68 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_intr.c b/sys/arm/broadcom/bcm2835/bcm2835_intr.c
index f3a5a2832845..249b86703fd6 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_intr.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_intr.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
index 56413beb6280..bd1762f88963 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
@@ -78,13 +78,15 @@ bcm2835_late_init(platform_t plat)
system = OF_finddevice("/system");
if (system != 0) {
- len = OF_getprop(system, "linux,serial", &cells, sizeof(cells));
+ len = OF_getencprop(system, "linux,serial", cells,
+ sizeof(cells));
if (len > 0)
- board_set_serial(fdt64_to_cpu(*((uint64_t *)cells)));
+ board_set_serial(((uint64_t)cells[0]) << 32 | cells[1]);
- len = OF_getprop(system, "linux,revision", &cells, sizeof(cells));
+ len = OF_getencprop(system, "linux,revision", cells,
+ sizeof(cells));
if (len > 0)
- board_set_revision(fdt32_to_cpu(*((uint32_t *)cells)));
+ board_set_revision(cells[0]);
}
}
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
index b74fefd958e1..f98d07df193c 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_spi.c b/sys/arm/broadcom/bcm2835/bcm2835_spi.c
index b30fac7819c9..dbfec6ea4f99 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_spi.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_spi.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_systimer.c b/sys/arm/broadcom/bcm2835/bcm2835_systimer.c
index 3fbaa903c59d..724e5efbc86b 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_systimer.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_systimer.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/machdep.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_wdog.c b/sys/arm/broadcom/bcm2835/bcm2835_wdog.c
index 39b16e34c5c8..7a11b660a4ee 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_wdog.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_wdog.c
@@ -34,7 +34,6 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/rman.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/conf/GENERIC b/sys/arm/conf/GENERIC
index f32f2e5fd17e..93a9b802e82e 100644
--- a/sys/arm/conf/GENERIC
+++ b/sys/arm/conf/GENERIC
@@ -43,6 +43,7 @@ files "../nvidia/tegra124/files.tegra124"
files "../qemu/files.qemu"
files "../ti/files.ti"
files "../ti/am335x/files.am335x"
+files "../ti/omap4/files.omap4"
options SOC_ALLWINNER_A10
options SOC_ALLWINNER_A13
@@ -53,6 +54,7 @@ options SOC_ALLWINNER_A83T
options SOC_ALLWINNER_H3
options SOC_BCM2836
options SOC_TI_AM335X
+options SOC_OMAP4
options SCHED_ULE # ULE scheduler
options SMP # Enable multiple cores
@@ -80,6 +82,7 @@ device pmu
# ARM Generic Timer
device generic_timer
+device mpcore_timer
# MMC/SD/SDIO Card slot support
device sdhci # SD controller
@@ -129,6 +132,9 @@ device ti_i2c
device am335x_pmic # AM335x Power Management IC (TPC65217)
device am335x_rtc # RTC support (power management only)
#define am335x_dmtpps # Pulse Per Second capture driver
+device twl # TI TWLX0X0/TPS659x0 Power Management
+device twl_vreg # twl voltage regulation
+device twl_clks # twl external clocks
# GPIO
device gpio
@@ -182,18 +188,18 @@ device usfs
device loop
device ether
device vlan # 802.1Q VLAN support
-device mii
device bpf
-device emac # 10/100 integrated EMAC controller
-device dwc # 10/100/1000 integrated GMAC controller
-device awg # 10/100/1000 integrated EMAC controller
-
-# USB ethernet support, requires miibus
-device smcphy
-device smsc
+# Ethernet NICs that use the common MII bus controller code.
+# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
device miibus
+device awg # 10/100/1000 integrated EMAC controller
+device cpsw # TI Common Platform Ethernet Switch (CPSW)
+device dwc # 10/100/1000 integrated GMAC controller
+device emac # 10/100 integrated EMAC controller
+device smsc # SMSC LAN91C111
+
# Sound support
device sound
@@ -214,9 +220,12 @@ device ti_pruss
# Mailbox support
device ti_mbox
+# DMA controller
+device ti_sdma
+
# Extensible Firmware Interface
options EFI
# Flattened Device Tree
options FDT # Configure using FDT/DTB data
-makeoptions MODULES_EXTRA="dtb/allwinner dtb/nvidia dtb/rpi"
+makeoptions MODULES_EXTRA="dtb/allwinner dtb/am335x dtb/nvidia dtb/rpi dtb/omap4"
diff --git a/sys/arm/conf/PANDABOARD b/sys/arm/conf/PANDABOARD
index 4848cea6b034..2a0170d71abd 100644
--- a/sys/arm/conf/PANDABOARD
+++ b/sys/arm/conf/PANDABOARD
@@ -28,12 +28,13 @@ ident PANDABOARD
hints "PANDABOARD.hints"
include "std.armv6"
-include "../ti/omap4/pandaboard/std.pandaboard"
+include "../ti/omap4/std.omap4"
makeoptions MODULES_EXTRA=dtb/omap4
options SCHED_ULE # ULE scheduler
options PLATFORM
+options PLATFORM_SMP
options SMP # Enable multiple cores
# NFS root from boopt/dhcp
diff --git a/sys/arm/freescale/imx/imx51_ccm.c b/sys/arm/freescale/imx/imx51_ccm.c
index 7a05d1e68306..e58c7abcae84 100644
--- a/sys/arm/freescale/imx/imx51_ccm.c
+++ b/sys/arm/freescale/imx/imx51_ccm.c
@@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/imx/imx51_ipuv3.c b/sys/arm/freescale/imx/imx51_ipuv3.c
index a96b1852eb6a..b88bb3fdb5d3 100644
--- a/sys/arm/freescale/imx/imx51_ipuv3.c
+++ b/sys/arm/freescale/imx/imx51_ipuv3.c
@@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -313,10 +312,10 @@ ipu3_fb_attach(device_t dev)
* On i.MX53, the offset is 0.
*/
node = ofw_bus_get_node(dev);
- if ((OF_getprop(node, "reg", &reg, sizeof(reg))) <= 0)
+ if ((OF_getencprop(node, "reg", &reg, sizeof(reg))) <= 0)
base = 0;
else
- base = fdt32_to_cpu(reg) - IPU_CM_BASE(0);
+ base = reg - IPU_CM_BASE(0);
/* map controller registers */
err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh);
if (err)
diff --git a/sys/arm/freescale/imx/imx51_ipuv3_fbd.c b/sys/arm/freescale/imx/imx51_ipuv3_fbd.c
index 800244a80cd6..ee6833fc3921 100644
--- a/sys/arm/freescale/imx/imx51_ipuv3_fbd.c
+++ b/sys/arm/freescale/imx/imx51_ipuv3_fbd.c
@@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$");
#include <machine/frame.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -222,10 +221,10 @@ ipu3_fb_attach(device_t dev)
* On i.MX53, the offset is 0.
*/
node = ofw_bus_get_node(dev);
- if ((OF_getprop(node, "reg", &reg, sizeof(reg))) <= 0)
+ if ((OF_getencprop(node, "reg", &reg, sizeof(reg))) <= 0)
base = 0;
else
- base = fdt32_to_cpu(reg) - IPU_CM_BASE(0);
+ base = reg - IPU_CM_BASE(0);
/* map controller registers */
err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh);
if (err)
diff --git a/sys/arm/freescale/imx/imx6_audmux.c b/sys/arm/freescale/imx/imx6_audmux.c
index 3b08a142a43e..61ec0b6da510 100644
--- a/sys/arm/freescale/imx/imx6_audmux.c
+++ b/sys/arm/freescale/imx/imx6_audmux.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timeet.h>
#include <sys/timetc.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/imx/imx6_ipu.c b/sys/arm/freescale/imx/imx6_ipu.c
index f561fa77ffd0..426ef474ef70 100644
--- a/sys/arm/freescale/imx/imx6_ipu.c
+++ b/sys/arm/freescale/imx/imx6_ipu.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/imx/imx6_sdma.c b/sys/arm/freescale/imx/imx6_sdma.c
index 4839270e7cc8..aa39ea93289b 100644
--- a/sys/arm/freescale/imx/imx6_sdma.c
+++ b/sys/arm/freescale/imx/imx6_sdma.c
@@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_kern.h>
#include <vm/pmap.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/imx/imx6_ssi.c b/sys/arm/freescale/imx/imx6_ssi.c
index 9000ae3ec9d9..4f4dadb99c81 100644
--- a/sys/arm/freescale/imx/imx6_ssi.c
+++ b/sys/arm/freescale/imx/imx6_ssi.c
@@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include <dev/sound/chip.h>
#include <mixer_if.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -447,12 +446,12 @@ find_sdma_controller(struct sc_info *sc)
if ((len = OF_getproplen(node, "dmas")) <= 0)
return (ENXIO);
- OF_getprop(node, "dmas", &dts_value, len);
+ OF_getencprop(node, "dmas", &dts_value, len);
- sc->sdma_ev_rx = fdt32_to_cpu(dts_value[1]);
- sc->sdma_ev_tx = fdt32_to_cpu(dts_value[5]);
+ sc->sdma_ev_rx = dts_value[1];
+ sc->sdma_ev_tx = dts_value[5];
- sdma_node = OF_node_from_xref(fdt32_to_cpu(dts_value[0]));
+ sdma_node = OF_node_from_xref(dts_value[0]);
sdma_sc = NULL;
diff --git a/sys/arm/freescale/imx/imx_gpio.c b/sys/arm/freescale/imx/imx_gpio.c
index 922548e33cbd..1c308dbbd687 100644
--- a/sys/arm/freescale/imx/imx_gpio.c
+++ b/sys/arm/freescale/imx/imx_gpio.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/resource.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/gpio/gpiobusvar.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/freescale/imx/imx_gpt.c b/sys/arm/freescale/imx/imx_gpt.c
index 8da0b2e0791f..f0eb7665dc07 100644
--- a/sys/arm/freescale/imx/imx_gpt.c
+++ b/sys/arm/freescale/imx/imx_gpt.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/imx/imx_i2c.c b/sys/arm/freescale/imx/imx_i2c.c
index 2e453dacc32a..c679c2fc56fc 100644
--- a/sys/arm/freescale/imx/imx_i2c.c
+++ b/sys/arm/freescale/imx/imx_i2c.c
@@ -63,7 +63,6 @@ __FBSDID("$FreeBSD$");
#include <dev/iicbus/iicbus.h>
#include "iicbus_if.h"
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/imx/imx_iomux.c b/sys/arm/freescale/imx/imx_iomux.c
index be3a3e81b22f..c9de2a31f8db 100644
--- a/sys/arm/freescale/imx/imx_iomux.c
+++ b/sys/arm/freescale/imx/imx_iomux.c
@@ -59,11 +59,10 @@
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
-#include <dev/fdt/fdt_pinctrl.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/fdt/fdt_pinctrl.h>
#include <arm/freescale/imx/imx_iomuxvar.h>
#include <arm/freescale/imx/imx_machdep.h>
diff --git a/sys/arm/freescale/imx/imx_wdog.c b/sys/arm/freescale/imx/imx_wdog.c
index cbf9343b1c60..f1e450102a85 100644
--- a/sys/arm/freescale/imx/imx_wdog.c
+++ b/sys/arm/freescale/imx/imx_wdog.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/imx/tzic.c b/sys/arm/freescale/imx/tzic.c
index 0f3cf5cc075f..e1b0635418d9 100644
--- a/sys/arm/freescale/imx/tzic.c
+++ b/sys/arm/freescale/imx/tzic.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/vybrid/vf_adc.c b/sys/arm/freescale/vybrid/vf_adc.c
index 0a806fb96c7d..7a506b89300e 100644
--- a/sys/arm/freescale/vybrid/vf_adc.c
+++ b/sys/arm/freescale/vybrid/vf_adc.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timeet.h>
#include <sys/timetc.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/vybrid/vf_anadig.c b/sys/arm/freescale/vybrid/vf_anadig.c
index 3a2cbc4e4811..411c3a1cd9f5 100644
--- a/sys/arm/freescale/vybrid/vf_anadig.c
+++ b/sys/arm/freescale/vybrid/vf_anadig.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#include <sys/watchdog.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/vybrid/vf_common.c b/sys/arm/freescale/vybrid/vf_common.c
index d57748172822..9c3082b6800b 100644
--- a/sys/arm/freescale/vybrid/vf_common.c
+++ b/sys/arm/freescale/vybrid/vf_common.c
@@ -32,7 +32,6 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/kernel.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
@@ -44,16 +43,15 @@ void
cpu_reset(void)
{
phandle_t src;
- uint32_t addr, paddr;
+ uint32_t paddr;
bus_addr_t vaddr;
if (src_swreset() == 0)
goto end;
src = OF_finddevice("src");
- if ((src != 0) && (OF_getprop(src, "reg", &paddr, sizeof(paddr))) > 0) {
- addr = fdt32_to_cpu(paddr);
- if (bus_space_map(fdtbus_bs_tag, addr, 0x10, 0, &vaddr) == 0) {
+ if ((src != 0) && (OF_getencprop(src, "reg", &paddr, sizeof(paddr))) > 0) {
+ if (bus_space_map(fdtbus_bs_tag, paddr, 0x10, 0, &vaddr) == 0) {
bus_space_write_4(fdtbus_bs_tag, vaddr, 0x00, SW_RST);
}
}
@@ -61,24 +59,3 @@ cpu_reset(void)
end:
while (1);
}
-
-#ifndef INTRNG
-static int
-fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
- int *pol)
-{
-
- if (!fdt_is_compatible(node, "arm,gic"))
- return (ENXIO);
-
- *interrupt = fdt32_to_cpu(intr[0]);
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
- return (0);
-}
-
-fdt_pic_decode_t fdt_pic_table[] = {
- &fdt_pic_decode_ic,
- NULL
-};
-#endif
diff --git a/sys/arm/freescale/vybrid/vf_dcu4.c b/sys/arm/freescale/vybrid/vf_dcu4.c
index 34dea4600a96..7fbf4a36ebb7 100644
--- a/sys/arm/freescale/vybrid/vf_dcu4.c
+++ b/sys/arm/freescale/vybrid/vf_dcu4.c
@@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -246,37 +245,37 @@ get_panel_info(struct dcu_softc *sc, struct panel_info *panel)
/* panel size */
if ((len = OF_getproplen(node, "panel-size")) <= 0)
return (ENXIO);
- OF_getprop(node, "panel-size", &dts_value, len);
- panel->width = fdt32_to_cpu(dts_value[0]);
- panel->height = fdt32_to_cpu(dts_value[1]);
+ OF_getencprop(node, "panel-size", dts_value, len);
+ panel->width = dts_value[0];
+ panel->height = dts_value[1];
/* hsync */
if ((len = OF_getproplen(node, "panel-hsync")) <= 0)
return (ENXIO);
- OF_getprop(node, "panel-hsync", &dts_value, len);
- panel->h_back_porch = fdt32_to_cpu(dts_value[0]);
- panel->h_pulse_width = fdt32_to_cpu(dts_value[1]);
- panel->h_front_porch = fdt32_to_cpu(dts_value[2]);
+ OF_getencprop(node, "panel-hsync", dts_value, len);
+ panel->h_back_porch = dts_value[0];
+ panel->h_pulse_width = dts_value[1];
+ panel->h_front_porch = dts_value[2];
/* vsync */
if ((len = OF_getproplen(node, "panel-vsync")) <= 0)
return (ENXIO);
- OF_getprop(node, "panel-vsync", &dts_value, len);
- panel->v_back_porch = fdt32_to_cpu(dts_value[0]);
- panel->v_pulse_width = fdt32_to_cpu(dts_value[1]);
- panel->v_front_porch = fdt32_to_cpu(dts_value[2]);
+ OF_getencprop(node, "panel-vsync", dts_value, len);
+ panel->v_back_porch = dts_value[0];
+ panel->v_pulse_width = dts_value[1];
+ panel->v_front_porch = dts_value[2];
/* clk divider */
if ((len = OF_getproplen(node, "panel-clk-div")) <= 0)
return (ENXIO);
- OF_getprop(node, "panel-clk-div", &dts_value, len);
- panel->clk_div = fdt32_to_cpu(dts_value[0]);
+ OF_getencprop(node, "panel-clk-div", dts_value, len);
+ panel->clk_div = dts_value[0];
/* backlight pin */
if ((len = OF_getproplen(node, "panel-backlight-pin")) <= 0)
return (ENXIO);
- OF_getprop(node, "panel-backlight-pin", &dts_value, len);
- panel->backlight_pin = fdt32_to_cpu(dts_value[0]);
+ OF_getencprop(node, "panel-backlight-pin", dts_value, len);
+ panel->backlight_pin = dts_value[0];
return (0);
}
diff --git a/sys/arm/freescale/vybrid/vf_dmamux.c b/sys/arm/freescale/vybrid/vf_dmamux.c
index a887ffa16d99..3e6b84e1ef5e 100644
--- a/sys/arm/freescale/vybrid/vf_dmamux.c
+++ b/sys/arm/freescale/vybrid/vf_dmamux.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#include <sys/watchdog.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/vybrid/vf_edma.c b/sys/arm/freescale/vybrid/vf_edma.c
index 93179216a5b2..eb6e514840d2 100644
--- a/sys/arm/freescale/vybrid/vf_edma.c
+++ b/sys/arm/freescale/vybrid/vf_edma.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#include <sys/watchdog.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -284,8 +283,8 @@ edma_attach(device_t dev)
if ((len = OF_getproplen(node, "device-id")) <= 0)
return (ENXIO);
- OF_getprop(node, "device-id", &dts_value, len);
- sc->device_id = fdt32_to_cpu(dts_value);
+ OF_getencprop(node, "device-id", &dts_value, len);
+ sc->device_id = dts_value;
sc->dma_stop = dma_stop;
sc->dma_setup = dma_setup;
diff --git a/sys/arm/freescale/vybrid/vf_ehci.c b/sys/arm/freescale/vybrid/vf_ehci.c
index 0a7dc941fef3..9ac26d0513ca 100644
--- a/sys/arm/freescale/vybrid/vf_ehci.c
+++ b/sys/arm/freescale/vybrid/vf_ehci.c
@@ -55,8 +55,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/controller/ehci.h>
#include <dev/usb/controller/ehcireg.h>
-#include <dev/fdt/fdt_common.h>
-
#include <machine/bus.h>
#include <machine/resource.h>
diff --git a/sys/arm/freescale/vybrid/vf_gpio.c b/sys/arm/freescale/vybrid/vf_gpio.c
index 0c1cf82303d8..9cab805c287f 100644
--- a/sys/arm/freescale/vybrid/vf_gpio.c
+++ b/sys/arm/freescale/vybrid/vf_gpio.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/gpio.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/gpio/gpiobusvar.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/freescale/vybrid/vf_i2c.c b/sys/arm/freescale/vybrid/vf_i2c.c
index 8008d1af8973..6c634c069a90 100644
--- a/sys/arm/freescale/vybrid/vf_i2c.c
+++ b/sys/arm/freescale/vybrid/vf_i2c.c
@@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$");
#include "iicbus_if.h"
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/vybrid/vf_iomuxc.c b/sys/arm/freescale/vybrid/vf_iomuxc.c
index 95711d676476..c4e29fe89ccd 100644
--- a/sys/arm/freescale/vybrid/vf_iomuxc.c
+++ b/sys/arm/freescale/vybrid/vf_iomuxc.c
@@ -148,12 +148,12 @@ pinmux_set(struct iomuxc_softc *sc)
continue;
if ((len = OF_getproplen(child, "iomux_config")) > 0) {
- OF_getprop(child, "iomux_config", &iomux_config, len);
+ OF_getencprop(child, "iomux_config", iomux_config, len);
values = len / (sizeof(uint32_t));
for (i = 0; i < values; i += 2) {
- pin = fdt32_to_cpu(iomux_config[i]);
- pin_cfg = fdt32_to_cpu(iomux_config[i+1]);
+ pin = iomux_config[i];
+ pin_cfg = iomux_config[i+1];
#if 0
device_printf(sc->dev, "Set pin %d to 0x%08x\n",
pin, pin_cfg);
diff --git a/sys/arm/freescale/vybrid/vf_machdep.c b/sys/arm/freescale/vybrid/vf_machdep.c
index 15566a4f3837..6628a7608a47 100644
--- a/sys/arm/freescale/vybrid/vf_machdep.c
+++ b/sys/arm/freescale/vybrid/vf_machdep.c
@@ -42,8 +42,6 @@ __FBSDID("$FreeBSD$");
#include <machine/machdep.h>
#include <machine/platform.h>
-#include <dev/fdt/fdt_common.h>
-
vm_offset_t
platform_lastaddr(void)
{
diff --git a/sys/arm/freescale/vybrid/vf_mscm.c b/sys/arm/freescale/vybrid/vf_mscm.c
index 02850e58936f..1f78b45f3098 100644
--- a/sys/arm/freescale/vybrid/vf_mscm.c
+++ b/sys/arm/freescale/vybrid/vf_mscm.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#include <sys/watchdog.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/vybrid/vf_port.c b/sys/arm/freescale/vybrid/vf_port.c
index 6ff8bfcccb10..2c2be2907e5f 100644
--- a/sys/arm/freescale/vybrid/vf_port.c
+++ b/sys/arm/freescale/vybrid/vf_port.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#include <sys/watchdog.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/vybrid/vf_sai.c b/sys/arm/freescale/vybrid/vf_sai.c
index 83f689f87d24..8ff802a37f3f 100644
--- a/sys/arm/freescale/vybrid/vf_sai.c
+++ b/sys/arm/freescale/vybrid/vf_sai.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <dev/sound/chip.h>
#include <mixer_if.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -424,19 +423,19 @@ find_edma_controller(struct sc_info *sc)
if ((len = OF_getproplen(node, "edma-mux-group")) <= 0)
return (ENXIO);
- OF_getprop(node, "edma-src-transmit", &dts_value, len);
- edma_src_transmit = fdt32_to_cpu(dts_value);
- OF_getprop(node, "edma-mux-group", &dts_value, len);
- edma_mux_group = fdt32_to_cpu(dts_value);
- OF_getprop(node, "edma-controller", &dts_value, len);
- edma_node = OF_node_from_xref(fdt32_to_cpu(dts_value));
+ OF_getencprop(node, "edma-src-transmit", &dts_value, len);
+ edma_src_transmit = dts_value;
+ OF_getencprop(node, "edma-mux-group", &dts_value, len);
+ edma_mux_group = dts_value;
+ OF_getencprop(node, "edma-controller", &dts_value, len);
+ edma_node = OF_node_from_xref(dts_value);
if ((len = OF_getproplen(edma_node, "device-id")) <= 0) {
return (ENXIO);
}
- OF_getprop(edma_node, "device-id", &dts_value, len);
- edma_device_id = fdt32_to_cpu(dts_value);
+ OF_getencprop(edma_node, "device-id", &dts_value, len);
+ edma_device_id = dts_value;
edma_sc = NULL;
diff --git a/sys/arm/freescale/vybrid/vf_spi.c b/sys/arm/freescale/vybrid/vf_spi.c
index 8fa466bf83bc..c089d01bfd3f 100644
--- a/sys/arm/freescale/vybrid/vf_spi.c
+++ b/sys/arm/freescale/vybrid/vf_spi.c
@@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include "spibus_if.h"
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/vybrid/vf_src.c b/sys/arm/freescale/vybrid/vf_src.c
index 83d7e969e09d..20fc59f6df02 100644
--- a/sys/arm/freescale/vybrid/vf_src.c
+++ b/sys/arm/freescale/vybrid/vf_src.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#include <sys/watchdog.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/freescale/vybrid/vf_tcon.c b/sys/arm/freescale/vybrid/vf_tcon.c
index 31f85b58b464..8bc256b1cc14 100644
--- a/sys/arm/freescale/vybrid/vf_tcon.c
+++ b/sys/arm/freescale/vybrid/vf_tcon.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#include <sys/watchdog.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/lpc/lpc_fb.c b/sys/arm/lpc/lpc_fb.c
index b2eab8b526a8..e4969159a45c 100644
--- a/sys/arm/lpc/lpc_fb.c
+++ b/sys/arm/lpc/lpc_fb.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -280,10 +279,9 @@ lpc_fb_intr(void *arg)
static int
lpc_fb_fdt_read(phandle_t node, const char *name, uint32_t *ret)
{
- if (OF_getprop(node, name, ret, sizeof(uint32_t)) <= 0)
+ if (OF_getencprop(node, name, ret, sizeof(uint32_t)) <= 0)
return (ENOENT);
- *ret = fdt32_to_cpu(*ret);
return (0);
}
diff --git a/sys/arm/lpc/lpc_intc.c b/sys/arm/lpc/lpc_intc.c
index d26ef9099c74..a5ee160b9f18 100644
--- a/sys/arm/lpc/lpc_intc.c
+++ b/sys/arm/lpc/lpc_intc.c
@@ -232,7 +232,7 @@ static int
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
{
- if (!fdt_is_compatible(node, "lpc,pic"))
+ if (!ofw_bus_node_is_compatible(node, "lpc,pic"))
return (ENXIO);
*interrupt = fdt32_to_cpu(intr[0]);
diff --git a/sys/arm/lpc/lpc_machdep.c b/sys/arm/lpc/lpc_machdep.c
index d193ac9f8d02..7a3c4b5b6c24 100644
--- a/sys/arm/lpc/lpc_machdep.c
+++ b/sys/arm/lpc/lpc_machdep.c
@@ -58,8 +58,6 @@ __FBSDID("$FreeBSD$");
#include <arm/lpc/lpcreg.h>
#include <arm/lpc/lpcvar.h>
-#include <dev/fdt/fdt_common.h>
-
vm_offset_t
platform_lastaddr(void)
{
diff --git a/sys/arm/lpc/lpc_timer.c b/sys/arm/lpc/lpc_timer.c
index ded53fa9931d..f745cf01b39c 100644
--- a/sys/arm/lpc/lpc_timer.c
+++ b/sys/arm/lpc/lpc_timer.c
@@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -158,7 +157,7 @@ lpc_timer_attach(device_t dev)
/* Get PERIPH_CLK encoded in parent bus 'bus-frequency' property */
node = ofw_bus_get_node(dev);
- if (OF_getprop(OF_parent(node), "bus-frequency", &freq,
+ if (OF_getencprop(OF_parent(node), "bus-frequency", &freq,
sizeof(pcell_t)) <= 0) {
bus_release_resources(dev, lpc_timer_spec, sc->lt_res);
bus_teardown_intr(dev, sc->lt_res[2], intrcookie);
@@ -166,8 +165,6 @@ lpc_timer_attach(device_t dev)
return (ENXIO);
}
- freq = fdt32_to_cpu(freq);
-
/* Set desired frequency in event timer and timecounter */
sc->lt_et.et_frequency = (uint64_t)freq;
lpc_timecounter.tc_frequency = (uint64_t)freq;
diff --git a/sys/arm/mv/armadaxp/armadaxp.c b/sys/arm/mv/armadaxp/armadaxp.c
index 172d3d71b4dc..29b2642f847d 100644
--- a/sys/arm/mv/armadaxp/armadaxp.c
+++ b/sys/arm/mv/armadaxp/armadaxp.c
@@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
#include <arm/mv/mvreg.h>
#include <arm/mv/mvvar.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <machine/fdt.h>
diff --git a/sys/arm/mv/gpio.c b/sys/arm/mv/gpio.c
index 79b7cc622a1c..70d3d06be43f 100644
--- a/sys/arm/mv/gpio.c
+++ b/sys/arm/mv/gpio.c
@@ -113,7 +113,7 @@ struct gpio_ctrl_entry {
gpios_phandler_t handler;
};
-int mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len);
+static int mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len);
int gpio_get_config_from_dt(void);
struct gpio_ctrl_entry gpio_controllers[] = {
@@ -540,7 +540,7 @@ mv_gpio_value_set(uint32_t pin, uint8_t val)
mv_gpio_reg_clear(reg, pin);
}
-int
+static int
mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len)
{
pcell_t gpio_cells, pincnt;
@@ -554,10 +554,8 @@ mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len)
/* Node is not a GPIO controller. */
return (ENXIO);
- if (OF_getprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0)
+ if (OF_getencprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0)
return (ENXIO);
-
- gpio_cells = fdt32_to_cpu(gpio_cells);
if (gpio_cells != 3)
return (ENXIO);
@@ -567,9 +565,9 @@ mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len)
if (fdt_regsize(ctrl, &gpio_ctrl, &size))
return (ENXIO);
- if (OF_getprop(ctrl, "pin-count", &pincnt, sizeof(pcell_t)) < 0)
+ if (OF_getencprop(ctrl, "pin-count", &pincnt, sizeof(pcell_t)) < 0)
return (ENXIO);
- sc.pin_num = fdt32_to_cpu(pincnt);
+ sc.pin_num = pincnt;
/*
* Skip controller reference, since controller's phandle is given
@@ -579,9 +577,9 @@ mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len)
gpios += inc;
for (t = 0; t < tuples; t++) {
- pin = fdt32_to_cpu(gpios[0]);
- dir = fdt32_to_cpu(gpios[1]);
- flags = fdt32_to_cpu(gpios[2]);
+ pin = gpios[0];
+ dir = gpios[1];
+ flags = gpios[2];
mv_gpio_configure(pin, flags);
@@ -630,7 +628,7 @@ mv_gpio_init(void)
return (ENXIO);
/* Get 'gpios' property. */
- OF_getprop(child, "gpios", &gpios, len);
+ OF_getencprop(child, "gpios", gpios, len);
e = (struct gpio_ctrl_entry *)&gpio_controllers;
@@ -641,9 +639,9 @@ mv_gpio_init(void)
* contain a ref. to a node defining GPIO
* controller.
*/
- ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0]));
+ ctrl = OF_node_from_xref(gpios[0]);
- if (fdt_is_compatible(ctrl, e->compat))
+ if (ofw_bus_node_is_compatible(ctrl, e->compat))
/* Call a handler. */
if ((rv = e->handler(ctrl,
(pcell_t *)&gpios, len)))
diff --git a/sys/arm/mv/mv_common.c b/sys/arm/mv/mv_common.c
index 497860f6d1e3..4f7f07c027b7 100644
--- a/sys/arm/mv/mv_common.c
+++ b/sys/arm/mv/mv_common.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
#include <machine/fdt.h>
@@ -230,7 +231,8 @@ fdt_pm(phandle_t node)
if (dev_mask & (1 << i))
continue;
- compat = fdt_is_compatible(node, fdt_pm_mask_table[i].compat);
+ compat = ofw_bus_node_is_compatible(node,
+ fdt_pm_mask_table[i].compat);
#if defined(SOC_MV_KIRKWOOD)
if (compat && (cpu_pm_ctrl & fdt_pm_mask_table[i].mask)) {
dev_mask |= (1 << i);
@@ -2092,7 +2094,7 @@ win_cpu_from_dt(void)
* Retrieve CESA SRAM data.
*/
if ((node = OF_finddevice("sram")) != -1)
- if (fdt_is_compatible(node, "mrvl,cesa-sram"))
+ if (ofw_bus_node_is_compatible(node, "mrvl,cesa-sram"))
goto moveon;
if ((node = OF_finddevice("/")) == 0)
@@ -2120,7 +2122,7 @@ moveon:
/* Check if there is a second CESA node */
while ((node = OF_peer(node)) != 0) {
- if (fdt_is_compatible(node, "mrvl,cesa-sram")) {
+ if (ofw_bus_node_is_compatible(node, "mrvl,cesa-sram")) {
if (fdt_regsize(node, &sram_base, &sram_size) != 0)
return (EINVAL);
break;
@@ -2170,7 +2172,7 @@ fdt_win_setup(void)
soc_node = &soc_nodes[i];
- if (!fdt_is_compatible(child, soc_node->compat))
+ if (!ofw_bus_node_is_compatible(child,soc_node->compat))
continue;
err = fdt_regsize(child, &base, &size);
@@ -2319,8 +2321,8 @@ fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
{
- if (!fdt_is_compatible(node, "mrvl,pic") &&
- !fdt_is_compatible(node, "mrvl,mpic"))
+ if (!ofw_bus_node_is_compatible(node, "mrvl,pic") &&
+ !ofw_bus_node_is_compatible(node, "mrvl,mpic"))
return (ENXIO);
*interrupt = fdt32_to_cpu(intr[0]);
diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c
index ce9766370ddc..b5bda0231467 100644
--- a/sys/arm/mv/mv_machdep.c
+++ b/sys/arm/mv/mv_machdep.c
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
#include <arm/mv/mvwin.h>
#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus_subr.h>
static int platform_mpp_init(void);
#if defined(SOC_MV_ARMADAXP)
@@ -103,7 +104,7 @@ platform_mpp_init(void)
* Try to access the MPP node directly i.e. through /aliases/mpp.
*/
if ((node = OF_finddevice("mpp")) != -1)
- if (fdt_is_compatible(node, "mrvl,mpp"))
+ if (ofw_bus_node_is_compatible(node, "mrvl,mpp"))
goto moveon;
/*
* Find the node the long way.
@@ -146,21 +147,19 @@ moveon:
/*
* Process 'pin-count' and 'pin-map' props.
*/
- if (OF_getprop(node, "pin-count", &pin_count, sizeof(pin_count)) <= 0)
+ if (OF_getencprop(node, "pin-count", &pin_count, sizeof(pin_count)) <= 0)
return (ENXIO);
- pin_count = fdt32_to_cpu(pin_count);
if (pin_count > MPP_PIN_MAX)
return (ERANGE);
- if (OF_getprop(node, "#pin-cells", &pin_cells, sizeof(pin_cells)) <= 0)
+ if (OF_getencprop(node, "#pin-cells", &pin_cells, sizeof(pin_cells)) <= 0)
pin_cells = MPP_PIN_CELLS;
- pin_cells = fdt32_to_cpu(pin_cells);
if (pin_cells > MPP_PIN_CELLS)
return (ERANGE);
tuple_size = sizeof(pcell_t) * pin_cells;
bzero(pinmap, sizeof(pinmap));
- len = OF_getprop(node, "pin-map", pinmap, sizeof(pinmap));
+ len = OF_getencprop(node, "pin-map", pinmap, sizeof(pinmap));
if (len <= 0)
return (ERANGE);
if (len % tuple_size)
@@ -175,8 +174,8 @@ moveon:
bzero(mpp, sizeof(mpp));
pinmap_ptr = pinmap;
for (i = 0; i < pins; i++) {
- mpp_pin = fdt32_to_cpu(*pinmap_ptr);
- mpp_function = fdt32_to_cpu(*(pinmap_ptr + 1));
+ mpp_pin = *pinmap_ptr;
+ mpp_function = *(pinmap_ptr + 1);
mpp[mpp_pin] = mpp_function;
pinmap_ptr += pin_cells;
}
@@ -290,8 +289,8 @@ platform_sram_devmap(struct devmap_entry *map)
* SRAM range.
*/
if ((child = OF_finddevice("/sram")) != 0)
- if (fdt_is_compatible(child, "mrvl,cesa-sram") ||
- fdt_is_compatible(child, "mrvl,scratchpad"))
+ if (ofw_bus_node_is_compatible(child, "mrvl,cesa-sram") ||
+ ofw_bus_node_is_compatible(child, "mrvl,scratchpad"))
goto moveon;
if ((root = OF_finddevice("/")) == 0)
@@ -406,14 +405,12 @@ platform_devmap_init(void)
i += 2;
}
- if (fdt_is_compatible(child, "mrvl,lbc")) {
+ if (ofw_bus_node_is_compatible(child, "mrvl,lbc")) {
/* Check available space */
- if (OF_getprop(child, "bank-count", (void *)&bank_count,
+ if (OF_getencprop(child, "bank-count", &bank_count,
sizeof(bank_count)) <= 0)
/* If no property, use default value */
bank_count = 1;
- else
- bank_count = fdt32_to_cpu(bank_count);
if ((i + bank_count) >= FDT_DEVMAP_MAX)
return (ENOMEM);
diff --git a/sys/arm/mv/mv_pci.c b/sys/arm/mv/mv_pci.c
index 55d3f15bb897..7f6b1f7da208 100644
--- a/sys/arm/mv/mv_pci.c
+++ b/sys/arm/mv/mv_pci.c
@@ -429,12 +429,12 @@ mv_pcib_attach(device_t self)
node = ofw_bus_get_node(self);
parnode = OF_parent(node);
- if (fdt_is_compatible(node, "mrvl,pcie")) {
+ if (ofw_bus_node_is_compatible(node, "mrvl,pcie")) {
sc->sc_type = MV_TYPE_PCIE;
sc->sc_win_target = MV_WIN_PCIE_TARGET(unit);
sc->sc_mem_win_attr = MV_WIN_PCIE_MEM_ATTR(unit);
sc->sc_io_win_attr = MV_WIN_PCIE_IO_ATTR(unit);
- } else if (fdt_is_compatible(node, "mrvl,pci")) {
+ } else if (ofw_bus_node_is_compatible(node, "mrvl,pci")) {
sc->sc_type = MV_TYPE_PCI;
sc->sc_win_target = MV_WIN_PCI_TARGET;
sc->sc_mem_win_attr = MV_WIN_PCI_MEM_ATTR;
diff --git a/sys/arm/mv/mv_ts.c b/sys/arm/mv/mv_ts.c
index 35cd06221e43..3ed8ab748d1e 100644
--- a/sys/arm/mv/mv_ts.c
+++ b/sys/arm/mv/mv_ts.c
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/sysctl.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/nvidia/tegra124/tegra124_machdep.c b/sys/arm/nvidia/tegra124/tegra124_machdep.c
index 0e881cc83ad1..b874b5abd0f3 100644
--- a/sys/arm/nvidia/tegra124/tegra124_machdep.c
+++ b/sys/arm/nvidia/tegra124/tegra124_machdep.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/machdep.h>
#include <machine/platformvar.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <arm/nvidia/tegra124/tegra124_mp.h>
diff --git a/sys/arm/nvidia/tegra124/tegra124_pmc.c b/sys/arm/nvidia/tegra124/tegra124_pmc.c
index 04ff73cd1d9b..cae31238037f 100644
--- a/sys/arm/nvidia/tegra124/tegra124_pmc.c
+++ b/sys/arm/nvidia/tegra124/tegra124_pmc.c
@@ -38,7 +38,6 @@
#include <dev/extres/clk/clk.h>
#include <dev/extres/hwreset/hwreset.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/nvidia/tegra_abpmisc.c b/sys/arm/nvidia/tegra_abpmisc.c
index 56d91b7caa91..d51ec2e9729c 100644
--- a/sys/arm/nvidia/tegra_abpmisc.c
+++ b/sys/arm/nvidia/tegra_abpmisc.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <sys/rman.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/nvidia/tegra_ahci.c b/sys/arm/nvidia/tegra_ahci.c
index bfa34132581a..2ea714a77641 100644
--- a/sys/arm/nvidia/tegra_ahci.c
+++ b/sys/arm/nvidia/tegra_ahci.c
@@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$");
#include <dev/extres/hwreset/hwreset.h>
#include <dev/extres/phy/phy.h>
#include <dev/extres/regulator/regulator.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/fdt/fdt_pinctrl.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/nvidia/tegra_efuse.c b/sys/arm/nvidia/tegra_efuse.c
index 34e0da00f0ed..13d97abd0335 100644
--- a/sys/arm/nvidia/tegra_efuse.c
+++ b/sys/arm/nvidia/tegra_efuse.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <dev/extres/clk/clk.h>
#include <dev/extres/hwreset/hwreset.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/nvidia/tegra_gpio.c b/sys/arm/nvidia/tegra_gpio.c
index d715a692a4cf..7626d3072bee 100644
--- a/sys/arm/nvidia/tegra_gpio.c
+++ b/sys/arm/nvidia/tegra_gpio.c
@@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/resource.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/gpio/gpiobusvar.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/nvidia/tegra_i2c.c b/sys/arm/nvidia/tegra_i2c.c
index f88768e6939a..ed0074277d02 100644
--- a/sys/arm/nvidia/tegra_i2c.c
+++ b/sys/arm/nvidia/tegra_i2c.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <dev/extres/clk/clk.h>
#include <dev/extres/hwreset/hwreset.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/iicbus/iiconf.h>
#include <dev/iicbus/iicbus.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/nvidia/tegra_pcie.c b/sys/arm/nvidia/tegra_pcie.c
index 4fe7c7102617..e62f35308e41 100644
--- a/sys/arm/nvidia/tegra_pcie.c
+++ b/sys/arm/nvidia/tegra_pcie.c
@@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
#include <dev/extres/hwreset/hwreset.h>
#include <dev/extres/phy/phy.h>
#include <dev/extres/regulator/regulator.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/ofw_pci.h>
diff --git a/sys/arm/nvidia/tegra_rtc.c b/sys/arm/nvidia/tegra_rtc.c
index 09a7c74728a5..2a783735f4bf 100644
--- a/sys/arm/nvidia/tegra_rtc.c
+++ b/sys/arm/nvidia/tegra_rtc.c
@@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <dev/extres/clk/clk.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/nvidia/tegra_uart.c b/sys/arm/nvidia/tegra_uart.c
index c70303ff5e08..05c306931e35 100644
--- a/sys/arm/nvidia/tegra_uart.c
+++ b/sys/arm/nvidia/tegra_uart.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <dev/extres/clk/clk.h>
#include <dev/extres/hwreset/hwreset.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/uart/uart.h>
@@ -248,4 +247,4 @@ static driver_t tegra_uart_driver = {
};
DRIVER_MODULE(tegra_uart, simplebus, tegra_uart_driver, uart_devclass,
- 0, 0); \ No newline at end of file
+ 0, 0);
diff --git a/sys/arm/nvidia/tegra_usbphy.c b/sys/arm/nvidia/tegra_usbphy.c
index d1c6eeb45cf2..811c5a878bd3 100644
--- a/sys/arm/nvidia/tegra_usbphy.c
+++ b/sys/arm/nvidia/tegra_usbphy.c
@@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$");
#include <dev/extres/hwreset/hwreset.h>
#include <dev/extres/phy/phy.h>
#include <dev/extres/regulator/regulator.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/fdt/fdt_pinctrl.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/rockchip/files.rk30xx b/sys/arm/rockchip/files.rk30xx
index 274748a0e186..b058ed91c574 100644
--- a/sys/arm/rockchip/files.rk30xx
+++ b/sys/arm/rockchip/files.rk30xx
@@ -1,7 +1,6 @@
# $FreeBSD$
kern/kern_clocksource.c standard
-arm/rockchip/rk30xx_common.c standard
arm/rockchip/rk30xx_machdep.c standard
arm/rockchip/rk30xx_pmu.c standard
arm/rockchip/rk30xx_grf.c standard
diff --git a/sys/arm/rockchip/rk30xx_gpio.c b/sys/arm/rockchip/rk30xx_gpio.c
index 609eb6af6c94..75bfd0034041 100644
--- a/sys/arm/rockchip/rk30xx_gpio.c
+++ b/sys/arm/rockchip/rk30xx_gpio.c
@@ -526,10 +526,8 @@ rk30_gpios_prop_handle(phandle_t ctrl, pcell_t *gpios, int len)
if (sc == NULL)
return ENXIO;
- if (OF_getprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0)
+ if (OF_getencprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0)
return (ENXIO);
-
- gpio_cells = fdt32_to_cpu(gpio_cells);
if (gpio_cells != 2)
return (ENXIO);
@@ -546,9 +544,9 @@ rk30_gpios_prop_handle(phandle_t ctrl, pcell_t *gpios, int len)
inc = sizeof(ihandle_t) / sizeof(pcell_t);
gpios += inc;
for (t = 0; t < tuples; t++) {
- pin = fdt32_to_cpu(gpios[0]);
- dir = fdt32_to_cpu(gpios[1]);
- flags = fdt32_to_cpu(gpios[2]);
+ pin = gpios[0];
+ dir = gpios[1];
+ flags = gpios[2];
for (i = 0; i < sc->sc_gpio_npins; i++) {
if (sc->sc_gpio_pins[i].gp_pin == pin)
@@ -601,7 +599,7 @@ rk30_gpio_init(void)
return (ENXIO);
/* Get 'gpios' property. */
- OF_getprop(child, "gpios", &gpios, len);
+ OF_getencprop(child, "gpios", gpios, len);
e = (struct gpio_ctrl_entry *)&gpio_controllers;
@@ -612,9 +610,9 @@ rk30_gpio_init(void)
* contain a ref. to a node defining GPIO
* controller.
*/
- ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0]));
+ ctrl = OF_node_from_xref(gpios[0]);
- if (fdt_is_compatible(ctrl, e->compat))
+ if (ofw_bus_node_is_compatible(ctrl, e->compat))
/* Call a handler. */
if ((rv = e->handler(ctrl,
(pcell_t *)&gpios, len)))
diff --git a/sys/arm/rockchip/rk30xx_grf.c b/sys/arm/rockchip/rk30xx_grf.c
index ce61e8c4e5fd..6261928ff110 100644
--- a/sys/arm/rockchip/rk30xx_grf.c
+++ b/sys/arm/rockchip/rk30xx_grf.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/rockchip/rk30xx_machdep.c b/sys/arm/rockchip/rk30xx_machdep.c
index bb3731504d90..d45ef8d4c045 100644
--- a/sys/arm/rockchip/rk30xx_machdep.c
+++ b/sys/arm/rockchip/rk30xx_machdep.c
@@ -47,8 +47,6 @@ __FBSDID("$FreeBSD$");
#include <machine/machdep.h>
#include <machine/platform.h>
-#include <dev/fdt/fdt_common.h>
-
#include <arm/rockchip/rk30xx_wdog.h>
vm_offset_t
diff --git a/sys/arm/rockchip/rk30xx_pmu.c b/sys/arm/rockchip/rk30xx_pmu.c
index 514e961d0d13..a3d1bd74cbad 100644
--- a/sys/arm/rockchip/rk30xx_pmu.c
+++ b/sys/arm/rockchip/rk30xx_pmu.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/rockchip/rk30xx_wdog.c b/sys/arm/rockchip/rk30xx_wdog.c
index 32ef5bdb0299..612b793fcbe4 100644
--- a/sys/arm/rockchip/rk30xx_wdog.c
+++ b/sys/arm/rockchip/rk30xx_wdog.c
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/rman.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/samsung/exynos/exynos5_common.c b/sys/arm/samsung/exynos/exynos5_common.c
index 04021c1cb919..c5174d48b26f 100644
--- a/sys/arm/samsung/exynos/exynos5_common.c
+++ b/sys/arm/samsung/exynos/exynos5_common.c
@@ -32,7 +32,6 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/kernel.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
@@ -48,24 +47,3 @@ cpu_reset(void)
while (1);
}
-
-#ifndef INTRNG
-static int
-fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
- int *pol)
-{
-
- if (!fdt_is_compatible(node, "arm,gic"))
- return (ENXIO);
-
- *interrupt = fdt32_to_cpu(intr[0]);
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
- return (0);
-}
-
-fdt_pic_decode_t fdt_pic_table[] = {
- &fdt_pic_decode_ic,
- NULL
-};
-#endif
diff --git a/sys/arm/ti/aintc.c b/sys/arm/ti/aintc.c
index 764f3a0726dc..ec2aad830590 100644
--- a/sys/arm/ti/aintc.c
+++ b/sys/arm/ti/aintc.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -298,13 +297,13 @@ static device_method_t ti_aintc_methods[] = {
};
static driver_t ti_aintc_driver = {
- "aintc",
+ "ti_aintc",
ti_aintc_methods,
sizeof(struct ti_aintc_softc),
};
static devclass_t ti_aintc_devclass;
-EARLY_DRIVER_MODULE(aintc, simplebus, ti_aintc_driver, ti_aintc_devclass,
+EARLY_DRIVER_MODULE(ti_aintc, simplebus, ti_aintc_driver, ti_aintc_devclass,
0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
SIMPLEBUS_PNP_INFO(compat_data);
diff --git a/sys/arm/ti/am335x/am335x_ecap.c b/sys/arm/ti/am335x/am335x_ecap.c
index eba5f722aedc..75b845f56e03 100644
--- a/sys/arm/ti/am335x/am335x_ecap.c
+++ b/sys/arm/ti/am335x/am335x_ecap.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/am335x/am335x_ehrpwm.c b/sys/arm/ti/am335x/am335x_ehrpwm.c
index 331331fcd94c..53cb3bb78249 100644
--- a/sys/arm/ti/am335x/am335x_ehrpwm.c
+++ b/sys/arm/ti/am335x/am335x_ehrpwm.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/am335x/am335x_gpio.c b/sys/arm/ti/am335x/am335x_gpio.c
index 63fc54429a7d..cbfde175c2e7 100644
--- a/sys/arm/ti/am335x/am335x_gpio.c
+++ b/sys/arm/ti/am335x/am335x_gpio.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <sys/gpio.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -66,8 +65,6 @@ static struct ofw_compat_data compat_data[] = {
static int
am335x_gpio_probe(device_t dev)
{
- if (ti_chip() != CHIP_AM335X)
- return (ENXIO);
if (!ofw_bus_status_okay(dev))
return (ENXIO);
@@ -75,6 +72,9 @@ am335x_gpio_probe(device_t dev)
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
+ if (ti_chip() != CHIP_AM335X)
+ return (ENXIO);
+
device_set_desc(dev, "TI AM335x General Purpose I/O (GPIO)");
return (0);
diff --git a/sys/arm/ti/am335x/am335x_lcd.c b/sys/arm/ti/am335x/am335x_lcd.c
index 8121ef58e7c6..c23aa24fb65d 100644
--- a/sys/arm/ti/am335x/am335x_lcd.c
+++ b/sys/arm/ti/am335x/am335x_lcd.c
@@ -359,13 +359,13 @@ am335x_read_property(device_t dev, phandle_t node, const char *name, uint32_t *v
{
pcell_t cell;
- if ((OF_getprop(node, name, &cell, sizeof(cell))) <= 0) {
+ if ((OF_getencprop(node, name, &cell, sizeof(cell))) <= 0) {
device_printf(dev, "missing '%s' attribute in LCD panel info\n",
name);
return (ENXIO);
}
- *val = fdt32_to_cpu(cell);
+ *val = cell;
return (0);
}
diff --git a/sys/arm/ti/am335x/am335x_lcd_syscons.c b/sys/arm/ti/am335x/am335x_lcd_syscons.c
index 2cbf2fcadad3..946722fb878d 100644
--- a/sys/arm/ti/am335x/am335x_lcd_syscons.c
+++ b/sys/arm/ti/am335x/am335x_lcd_syscons.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -351,7 +350,7 @@ am335x_syscons_find_panel_node(phandle_t start)
phandle_t result;
for (child = OF_child(start); child != 0; child = OF_peer(child)) {
- if (fdt_is_compatible(child, "ti,am335x-lcd"))
+ if (ofw_bus_node_is_compatible(child, "ti,am335x-lcd"))
return (child);
if ((result = am335x_syscons_find_panel_node(child)))
return (result);
@@ -383,13 +382,13 @@ am335x_syscons_configure(int flags)
root = OF_finddevice("/");
if ((root != 0) &&
(display = am335x_syscons_find_panel_node(root))) {
- if ((OF_getprop(display, "panel_width",
- &cell, sizeof(cell))) > 0)
- va_sc->width = (int)fdt32_to_cpu(cell);
+ if ((OF_getencprop(display, "panel_width", &cell,
+ sizeof(cell))) > 0)
+ va_sc->width = cell;
- if ((OF_getprop(display, "panel_height",
- &cell, sizeof(cell))) > 0)
- va_sc->height = (int)fdt32_to_cpu(cell);
+ if ((OF_getencprop(display, "panel_height", &cell,
+ sizeof(cell))) > 0)
+ va_sc->height = cell;
}
if (va_sc->width == 0)
diff --git a/sys/arm/ti/am335x/am335x_musb.c b/sys/arm/ti/am335x/am335x_musb.c
index c168493d0867..8abcc89079b5 100644
--- a/sys/arm/ti/am335x/am335x_musb.c
+++ b/sys/arm/ti/am335x/am335x_musb.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/priv.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/am335x/am335x_prcm.c b/sys/arm/ti/am335x/am335x_prcm.c
index f7934328e354..7f65f0f6b4a1 100644
--- a/sys/arm/ti/am335x/am335x_prcm.c
+++ b/sys/arm/ti/am335x/am335x_prcm.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <arm/ti/ti_scm.h>
#include <arm/ti/ti_prcm.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/am335x/am335x_pwmss.c b/sys/arm/ti/am335x/am335x_pwmss.c
index dbc613e91903..814865d6b762 100644
--- a/sys/arm/ti/am335x/am335x_pwmss.c
+++ b/sys/arm/ti/am335x/am335x_pwmss.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/fdt/simplebus.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/ti/am335x/am335x_scm_padconf.c b/sys/arm/ti/am335x/am335x_scm_padconf.c
index ebb65ddba2f6..619178563259 100644
--- a/sys/arm/ti/am335x/am335x_scm_padconf.c
+++ b/sys/arm/ti/am335x/am335x_scm_padconf.c
@@ -293,7 +293,7 @@ const static struct ti_pinmux_padconf ti_padconf_devmap[] = {
{ .ballname = NULL },
};
-const struct ti_pinmux_device ti_pinmux_dev = {
+const struct ti_pinmux_device ti_am335x_pinmux_dev = {
.padconf_muxmode_mask = 0x7,
.padconf_sate_mask = 0x78,
.padstate = ti_padstate_devmap,
diff --git a/sys/arm/ti/am335x/am335x_scm_padconf.h b/sys/arm/ti/am335x/am335x_scm_padconf.h
index 2d0cd4b9ccec..b1fa22bac6c7 100644
--- a/sys/arm/ti/am335x/am335x_scm_padconf.h
+++ b/sys/arm/ti/am335x/am335x_scm_padconf.h
@@ -42,4 +42,6 @@
#define PADCONF_INPUT_PULLDOWN (RXACTIVE)
#define PADCONF_INPUT_PULLUP_SLOW (PADCONF_INPUT_PULLUP | SLEWCTRL)
+extern const struct ti_pinmux_device ti_am335x_pinmux_dev;
+
#endif /* AM335X_SCM_PADCONF_H */
diff --git a/sys/arm/ti/am335x/am335x_usbss.c b/sys/arm/ti/am335x/am335x_usbss.c
index 6ddc562c5a91..8355faaa0f19 100644
--- a/sys/arm/ti/am335x/am335x_usbss.c
+++ b/sys/arm/ti/am335x/am335x_usbss.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/priv.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/fdt/simplebus.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/ti/cpsw/if_cpsw.c b/sys/arm/ti/cpsw/if_cpsw.c
index a7a7569dd98c..79bfa0d44ca8 100644
--- a/sys/arm/ti/cpsw/if_cpsw.c
+++ b/sys/arm/ti/cpsw/if_cpsw.c
@@ -76,7 +76,6 @@ __FBSDID("$FreeBSD$");
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/omap4/files.omap4 b/sys/arm/ti/omap4/files.omap4
index 1f331fc9066c..ddae056d3fc4 100644
--- a/sys/arm/ti/omap4/files.omap4
+++ b/sys/arm/ti/omap4/files.omap4
@@ -14,6 +14,8 @@ arm/ti/omap4/omap4_scm_padconf.c standard
arm/ti/omap4/omap4_mp.c optional smp
arm/ti/omap4/omap4_wugen.c standard
+arm/ti/omap4/pandaboard/pandaboard.c standard
+
arm/ti/twl/twl.c optional twl
arm/ti/twl/twl_vreg.c optional twl twl_vreg
arm/ti/twl/twl_clks.c optional twl twl_clks
diff --git a/sys/arm/ti/omap4/omap4_gpio.c b/sys/arm/ti/omap4/omap4_gpio.c
index dd38f4a6a56a..faf2339411b6 100644
--- a/sys/arm/ti/omap4/omap4_gpio.c
+++ b/sys/arm/ti/omap4/omap4_gpio.c
@@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -60,14 +59,14 @@ static struct ofw_compat_data compat_data[] = {
static int
omap4_gpio_probe(device_t dev)
{
- if (ti_chip() != CHIP_OMAP_4)
- return (ENXIO);
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
+ if (ti_chip() != CHIP_OMAP_4)
+ return (ENXIO);
device_set_desc(dev, "TI OMAP4 General Purpose I/O (GPIO)");
diff --git a/sys/arm/ti/omap4/omap4_mp.c b/sys/arm/ti/omap4/omap4_mp.c
index 055a8aad5f03..165cbcfb9936 100644
--- a/sys/arm/ti/omap4/omap4_mp.c
+++ b/sys/arm/ti/omap4/omap4_mp.c
@@ -38,20 +38,24 @@ __FBSDID("$FreeBSD$");
#include <machine/smp.h>
#include <machine/fdt.h>
#include <machine/intr.h>
+#include <machine/platformvar.h>
#include <arm/ti/ti_smc.h>
#include <arm/ti/omap4/omap4_smc.h>
+#include <arm/ti/omap4/omap4_mp.h>
void
-platform_mp_setmaxid(void)
+omap4_mp_setmaxid(platform_t plat)
{
+ if (mp_ncpus != 0)
+ return;
mp_maxid = 1;
mp_ncpus = 2;
}
void
-platform_mp_start_ap(void)
+omap4_mp_start_ap(platform_t plat)
{
bus_addr_t scu_addr;
diff --git a/sys/arm/ti/omap4/omap4_mp.h b/sys/arm/ti/omap4/omap4_mp.h
new file mode 100644
index 000000000000..d4aa8df876b3
--- /dev/null
+++ b/sys/arm/ti/omap4/omap4_mp.h
@@ -0,0 +1,33 @@
+/*-
+ * Copyright (c) 2016 Olivier Houchard <cognet@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 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 _OMAP4_MP_H_
+#define _OMAP4_MP_H_
+void omap4_mp_setmaxid(platform_t plat);
+void omap4_mp_start_ap(platform_t plat);
+#endif /* _OMAP4_MP_H_ */
+
diff --git a/sys/arm/ti/omap4/omap4_prcm_clks.c b/sys/arm/ti/omap4/omap4_prcm_clks.c
index 782e7ac71111..d350121d7a4d 100644
--- a/sys/arm/ti/omap4/omap4_prcm_clks.c
+++ b/sys/arm/ti/omap4/omap4_prcm_clks.c
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <arm/ti/ti_prcm.h>
#include <arm/ti/omap4/omap4_reg.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/omap4/omap4_scm_padconf.c b/sys/arm/ti/omap4/omap4_scm_padconf.c
index e43581e8db57..ada0e096f30a 100644
--- a/sys/arm/ti/omap4/omap4_scm_padconf.c
+++ b/sys/arm/ti/omap4/omap4_scm_padconf.c
@@ -295,7 +295,7 @@ const static struct ti_pinmux_padconf ti_padconf_devmap[] = {
{ .ballname = NULL },
};
-const struct ti_pinmux_device ti_pinmux_dev = {
+const struct ti_pinmux_device omap4_pinmux_dev = {
.padconf_muxmode_mask = CONTROL_PADCONF_MUXMODE_MASK,
.padconf_sate_mask = CONTROL_PADCONF_SATE_MASK,
.padstate = ti_padstate_devmap,
diff --git a/sys/arm/ti/omap4/omap4_scm_padconf.h b/sys/arm/ti/omap4/omap4_scm_padconf.h
index b0c12fe595e5..adee0a799cd3 100644
--- a/sys/arm/ti/omap4/omap4_scm_padconf.h
+++ b/sys/arm/ti/omap4/omap4_scm_padconf.h
@@ -78,4 +78,6 @@
| CONTROL_PADCONF_OFF_PULL_ENABLE)
#define PADCONF_PIN_OFF_WAKEUPENABLE CONTROL_PADCONF_WAKEUP_ENABLE
+extern const struct ti_pinmux_device omap4_pinmux_dev;
+
#endif /* OMAP4_SCM_PADCONF_H */
diff --git a/sys/arm/ti/omap4/pandaboard/files.pandaboard b/sys/arm/ti/omap4/pandaboard/files.pandaboard
deleted file mode 100644
index f658ffb3dc7b..000000000000
--- a/sys/arm/ti/omap4/pandaboard/files.pandaboard
+++ /dev/null
@@ -1,3 +0,0 @@
-# $FreeBSD$
-
-arm/ti/omap4/pandaboard/pandaboard.c standard
diff --git a/sys/arm/ti/omap4/pandaboard/pandaboard.c b/sys/arm/ti/omap4/pandaboard/pandaboard.c
index f557f736c56d..94996f6ca10d 100644
--- a/sys/arm/ti/omap4/pandaboard/pandaboard.c
+++ b/sys/arm/ti/omap4/pandaboard/pandaboard.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <machine/fdt.h>
#include <arm/ti/omap4/omap4_reg.h>
+#include <arm/ti/omap4/pandaboard/pandaboard.h>
/* Registers in the SCRM that control the AUX clocks */
#define SCRM_ALTCLKSRC (0x110)
@@ -111,8 +112,8 @@ __FBSDID("$FreeBSD$");
* RETURNS:
* nothing.
*/
-static void
-usb_hub_init(void)
+void
+pandaboard_usb_hub_init(void)
{
bus_space_handle_t scrm_addr, gpio1_addr, gpio2_addr, scm_addr;
@@ -169,39 +170,3 @@ usb_hub_init(void)
bus_space_unmap(fdtbus_bs_tag, gpio2_addr, OMAP44XX_GPIO2_SIZE);
bus_space_unmap(fdtbus_bs_tag, scm_addr, OMAP44XX_SCM_PADCONF_SIZE);
}
-
-/**
- * board_init - initialises the pandaboard
- * @dummy: ignored
- *
- * This function is called before any of the driver are initialised, which is
- * annoying because it means we can't use the SCM, PRCM and GPIO modules which
- * would really be useful.
- *
- * So we don't have:
- * - any drivers
- * - no interrupts
- *
- * What we do have:
- * - virt/phys mappings from the devmap (see omap4.c)
- * -
- *
- *
- * So we are hamstrung without the useful drivers and we have to go back to
- * direct register manupulation. Luckly we don't have to do to much, basically
- * just setup the usb hub/ethernet.
- *
- */
-static void
-board_init(void *dummy)
-{
- /* Initialise the USB phy and hub */
- usb_hub_init();
-
- /*
- * XXX Board identification e.g. read out from FPGA or similar should
- * go here
- */
-}
-
-SYSINIT(board_init, SI_SUB_CPU, SI_ORDER_THIRD, board_init, NULL);
diff --git a/sys/arm/ti/omap4/pandaboard/pandaboard.h b/sys/arm/ti/omap4/pandaboard/pandaboard.h
new file mode 100644
index 000000000000..8d48d5b80ec1
--- /dev/null
+++ b/sys/arm/ti/omap4/pandaboard/pandaboard.h
@@ -0,0 +1,32 @@
+/*-
+ * Copyright (c) 2016 Olivier Houchard <cognet@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 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 _PANDABOARD_H_
+#define _PANDABOARD_H_
+void pandaboard_usb_hub_init(void);
+#endif /* _OMAP4_MP_H_ */
+
diff --git a/sys/arm/ti/omap4/pandaboard/std.pandaboard b/sys/arm/ti/omap4/pandaboard/std.pandaboard
deleted file mode 100644
index 6a65f66bb13d..000000000000
--- a/sys/arm/ti/omap4/pandaboard/std.pandaboard
+++ /dev/null
@@ -1,4 +0,0 @@
-# $FreeBSD$
-
-include "../ti/omap4/std.omap4"
-files "../ti/omap4/pandaboard/files.pandaboard"
diff --git a/sys/arm/ti/ti_adc.c b/sys/arm/ti/ti_adc.c
index 154cd78b630a..2b49789f5cea 100644
--- a/sys/arm/ti/ti_adc.c
+++ b/sys/arm/ti/ti_adc.c
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -767,14 +766,17 @@ ti_adc_attach(device_t dev)
/* Read "tsc" node properties */
child = ofw_bus_find_child(node, "tsc");
if (child != 0 && OF_hasprop(child, "ti,wires")) {
- if ((OF_getprop(child, "ti,wires", &cell, sizeof(cell))) > 0)
- sc->sc_tsc_wires = fdt32_to_cpu(cell);
- if ((OF_getprop(child, "ti,coordinate-readouts", &cell, sizeof(cell))) > 0)
- sc->sc_coord_readouts = fdt32_to_cpu(cell);
- if ((OF_getprop(child, "ti,x-plate-resistance", &cell, sizeof(cell))) > 0)
- sc->sc_x_plate_resistance = fdt32_to_cpu(cell);
- if ((OF_getprop(child, "ti,charge-delay", &cell, sizeof(cell))) > 0)
- sc->sc_charge_delay = fdt32_to_cpu(cell);
+ if ((OF_getencprop(child, "ti,wires", &cell, sizeof(cell))) > 0)
+ sc->sc_tsc_wires = cell;
+ if ((OF_getencprop(child, "ti,coordinate-readouts", &cell,
+ sizeof(cell))) > 0)
+ sc->sc_coord_readouts = cell;
+ if ((OF_getencprop(child, "ti,x-plate-resistance", &cell,
+ sizeof(cell))) > 0)
+ sc->sc_x_plate_resistance = cell;
+ if ((OF_getencprop(child, "ti,charge-delay", &cell,
+ sizeof(cell))) > 0)
+ sc->sc_charge_delay = cell;
nwire_configs = OF_getencprop_alloc(child, "ti,wire-config",
sizeof(*wire_configs), (void **)&wire_configs);
if (nwire_configs != sc->sc_tsc_wires) {
diff --git a/sys/arm/ti/ti_cpuid.c b/sys/arm/ti/ti_cpuid.c
index 7043d93b8cfa..ca64c811dfaf 100644
--- a/sys/arm/ti/ti_cpuid.c
+++ b/sys/arm/ti/ti_cpuid.c
@@ -43,6 +43,10 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
#include <arm/ti/tivar.h>
#include <arm/ti/ti_cpuid.h>
@@ -268,6 +272,12 @@ am335x_get_revision(void)
static void
ti_cpu_ident(void *dummy)
{
+ phandle_t root;
+
+ root = OF_finddevice("/");
+ if (!ofw_bus_node_is_compatible(root, "ti,omap4") &&
+ !ofw_bus_node_is_compatible(root, "ti,am33xx"))
+ return;
switch(ti_chip()) {
case CHIP_OMAP_4:
omap4_get_revision();
diff --git a/sys/arm/ti/ti_cpuid.h b/sys/arm/ti/ti_cpuid.h
index 86ac98287267..715f080e5ff7 100644
--- a/sys/arm/ti/ti_cpuid.h
+++ b/sys/arm/ti/ti_cpuid.h
@@ -70,15 +70,12 @@
#define CHIP_OMAP_4 0
#define CHIP_AM335X 1
+extern int _ti_chip;
+
static __inline int ti_chip(void)
{
-#if defined(SOC_OMAP4)
- return CHIP_OMAP_4;
-#elif defined(SOC_TI_AM335X)
- return CHIP_AM335X;
-#else
-# error Chip type not defined, ensure SOC_xxxx is defined
-#endif
+ KASSERT(_ti_chip != -1, ("Can't determine TI Chip"));
+ return _ti_chip;
}
uint32_t ti_revision(void);
diff --git a/sys/arm/ti/ti_edma3.c b/sys/arm/ti/ti_edma3.c
index 080e7bddbe77..e12d82b3706f 100644
--- a/sys/arm/ti/ti_edma3.c
+++ b/sys/arm/ti/ti_edma3.c
@@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <machine/resource.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c
index fe2b5ff06bdf..4f0f4f35aeea 100644
--- a/sys/arm/ti/ti_gpio.c
+++ b/sys/arm/ti/ti_gpio.c
@@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$");
#include <arm/ti/ti_prcm.h>
#include <arm/ti/ti_hwmods.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/gpio/gpiobusvar.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
@@ -711,7 +710,8 @@ ti_gpio_detach(device_t dev)
/* Disable all interrupts */
if (sc->sc_mem_res != NULL)
ti_gpio_intr_clr(sc, 0xffffffff);
- gpiobus_detach_bus(dev);
+ if (sc->sc_busdev != NULL)
+ gpiobus_detach_bus(dev);
if (sc->sc_isrcs != NULL)
ti_gpio_pic_detach(sc);
/* Release the memory and IRQ resources. */
@@ -719,10 +719,12 @@ ti_gpio_detach(device_t dev)
bus_teardown_intr(dev, sc->sc_irq_res,
sc->sc_irq_hdl);
}
- bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid,
- sc->sc_irq_res);
- bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid,
- sc->sc_mem_res);
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid,
+ sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid,
+ sc->sc_mem_res);
TI_GPIO_LOCK_DESTROY(sc);
return (0);
diff --git a/sys/arm/ti/ti_hwmods.c b/sys/arm/ti/ti_hwmods.c
index e662d27e460c..1dfb074a7903 100644
--- a/sys/arm/ti/ti_hwmods.c
+++ b/sys/arm/ti/ti_hwmods.c
@@ -34,7 +34,6 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/kernel.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/ti_machdep.c b/sys/arm/ti/ti_machdep.c
index f9d83890ba86..23cfea021da6 100644
--- a/sys/arm/ti/ti_machdep.c
+++ b/sys/arm/ti/ti_machdep.c
@@ -53,11 +53,33 @@ __FBSDID("$FreeBSD$");
#include <machine/platformvar.h>
#include <arm/ti/omap4/omap4_reg.h>
+#include <arm/ti/omap4/omap4_mp.h>
+#include <arm/ti/ti_cpuid.h>
#include "platform_if.h"
void (*ti_cpu_reset)(void) = NULL;
+int _ti_chip = -1;
+
+#if defined(SOC_OMAP4)
+static int
+omap4_attach(platform_t plat)
+{
+ _ti_chip = CHIP_OMAP_4;
+ return (0);
+}
+#endif
+
+#if defined(SOC_TI_AM335X)
+static int
+ti_am335x_attach(platform_t plat)
+{
+ _ti_chip = CHIP_AM335X;
+ return (0);
+}
+#endif
+
static vm_offset_t
ti_lastaddr(platform_t plat)
{
@@ -106,17 +128,23 @@ ti_plat_cpu_reset(platform_t plat)
#if defined(SOC_OMAP4)
static platform_method_t omap4_methods[] = {
+ PLATFORMMETHOD(platform_attach, omap4_attach),
PLATFORMMETHOD(platform_devmap_init, ti_omap4_devmap_init),
PLATFORMMETHOD(platform_lastaddr, ti_lastaddr),
PLATFORMMETHOD(platform_cpu_reset, ti_plat_cpu_reset),
+#ifdef SMP
+ PLATFORMMETHOD(platform_mp_start_ap, omap4_mp_start_ap),
+ PLATFORMMETHOD(platform_mp_setmaxid, omap4_mp_setmaxid),
+#endif
PLATFORMMETHOD_END,
};
-FDT_PLATFORM_DEF(omap4, "omap4", 0, "ti,omap4430", 0);
+FDT_PLATFORM_DEF(omap4, "omap4", 0, "ti,omap4430", 200);
#endif
#if defined(SOC_TI_AM335X)
static platform_method_t am335x_methods[] = {
+ PLATFORMMETHOD(platform_attach, ti_am335x_attach),
PLATFORMMETHOD(platform_devmap_init, ti_am335x_devmap_init),
PLATFORMMETHOD(platform_lastaddr, ti_lastaddr),
PLATFORMMETHOD(platform_cpu_reset, ti_plat_cpu_reset),
@@ -124,5 +152,5 @@ static platform_method_t am335x_methods[] = {
PLATFORMMETHOD_END,
};
-FDT_PLATFORM_DEF(am335x, "am335x", 0, "ti,am335x", 200);
+FDT_PLATFORM_DEF(am335x, "am335x", 0, "ti,am33xx", 200);
#endif
diff --git a/sys/arm/ti/ti_mbox.c b/sys/arm/ti/ti_mbox.c
index 9729ed40fc4a..9747be13aac8 100644
--- a/sys/arm/ti/ti_mbox.c
+++ b/sys/arm/ti/ti_mbox.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <machine/frame.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/ti_pinmux.c b/sys/arm/ti/ti_pinmux.c
index d3daf76eca79..e102d61611ab 100644
--- a/sys/arm/ti/ti_pinmux.c
+++ b/sys/arm/ti/ti_pinmux.c
@@ -49,12 +49,14 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
-#include <dev/fdt/fdt_common.h>
-#include <dev/fdt/fdt_pinctrl.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/fdt/fdt_pinctrl.h>
+#include <arm/ti/omap4/omap4_scm_padconf.h>
+#include <arm/ti/am335x/am335x_scm_padconf.h>
+#include <arm/ti/ti_cpuid.h>
#include "ti_pinmux.h"
struct pincfg {
@@ -86,7 +88,7 @@ static struct ti_pinmux_softc *ti_pinmux_sc;
* files and is specific to the given SoC platform. Each entry in the array
* corresponds to an individual pin.
*/
-extern const struct ti_pinmux_device ti_pinmux_dev;
+static const struct ti_pinmux_device *ti_pinmux_dev;
/**
@@ -102,7 +104,7 @@ ti_pinmux_padconf_from_name(const char *ballname)
{
const struct ti_pinmux_padconf *padconf;
- padconf = ti_pinmux_dev.padconf;
+ padconf = ti_pinmux_dev->padconf;
while (padconf->ballname != NULL) {
if (strcmp(ballname, padconf->ballname) == 0)
return(padconf);
@@ -135,7 +137,7 @@ ti_pinmux_padconf_set_internal(struct ti_pinmux_softc *sc,
uint16_t reg_val;
/* populate the new value for the PADCONF register */
- reg_val = (uint16_t)(state & ti_pinmux_dev.padconf_sate_mask);
+ reg_val = (uint16_t)(state & ti_pinmux_dev->padconf_sate_mask);
/* find the new mode requested */
for (mode = 0; mode < 8; mode++) {
@@ -152,7 +154,7 @@ ti_pinmux_padconf_set_internal(struct ti_pinmux_softc *sc,
}
/* set the mux mode */
- reg_val |= (uint16_t)(mode & ti_pinmux_dev.padconf_muxmode_mask);
+ reg_val |= (uint16_t)(mode & ti_pinmux_dev->padconf_muxmode_mask);
if (bootverbose)
device_printf(sc->sc_dev, "setting internal %x for %s\n",
@@ -227,11 +229,11 @@ ti_pinmux_padconf_get(const char *padname, const char **muxmode,
/* save the state */
if (state)
- *state = (reg_val & ti_pinmux_dev.padconf_sate_mask);
+ *state = (reg_val & ti_pinmux_dev->padconf_sate_mask);
/* save the mode */
if (muxmode)
- *muxmode = padconf->muxmodes[(reg_val & ti_pinmux_dev.padconf_muxmode_mask)];
+ *muxmode = padconf->muxmodes[(reg_val & ti_pinmux_dev->padconf_muxmode_mask)];
return (0);
}
@@ -260,7 +262,7 @@ ti_pinmux_padconf_set_gpiomode(uint32_t gpio, unsigned int state)
return (ENXIO);
/* find the gpio pin in the padconf array */
- padconf = ti_pinmux_dev.padconf;
+ padconf = ti_pinmux_dev->padconf;
while (padconf->ballname != NULL) {
if (padconf->gpio_pin == gpio)
break;
@@ -270,10 +272,10 @@ ti_pinmux_padconf_set_gpiomode(uint32_t gpio, unsigned int state)
return (EINVAL);
/* populate the new value for the PADCONF register */
- reg_val = (uint16_t)(state & ti_pinmux_dev.padconf_sate_mask);
+ reg_val = (uint16_t)(state & ti_pinmux_dev->padconf_sate_mask);
/* set the mux mode */
- reg_val |= (uint16_t)(padconf->gpio_mode & ti_pinmux_dev.padconf_muxmode_mask);
+ reg_val |= (uint16_t)(padconf->gpio_mode & ti_pinmux_dev->padconf_muxmode_mask);
/* write the register value (16-bit writes) */
ti_pinmux_write_2(ti_pinmux_sc, padconf->reg_off, reg_val);
@@ -305,7 +307,7 @@ ti_pinmux_padconf_get_gpiomode(uint32_t gpio, unsigned int *state)
return (ENXIO);
/* find the gpio pin in the padconf array */
- padconf = ti_pinmux_dev.padconf;
+ padconf = ti_pinmux_dev->padconf;
while (padconf->ballname != NULL) {
if (padconf->gpio_pin == gpio)
break;
@@ -318,12 +320,12 @@ ti_pinmux_padconf_get_gpiomode(uint32_t gpio, unsigned int *state)
reg_val = ti_pinmux_read_2(ti_pinmux_sc, padconf->reg_off);
/* check to make sure the pins is configured as GPIO in the first state */
- if ((reg_val & ti_pinmux_dev.padconf_muxmode_mask) != padconf->gpio_mode)
+ if ((reg_val & ti_pinmux_dev->padconf_muxmode_mask) != padconf->gpio_mode)
return (EINVAL);
/* read and store the reset of the state, i.e. pull-up, pull-down, etc */
if (state)
- *state = (reg_val & ti_pinmux_dev.padconf_sate_mask);
+ *state = (reg_val & ti_pinmux_dev->padconf_sate_mask);
return (0);
}
@@ -382,6 +384,22 @@ ti_pinmux_probe(device_t dev)
__func__);
return (EEXIST);
}
+ switch (ti_chip()) {
+#ifdef SOC_OMAP4
+ case CHIP_OMAP_4:
+ ti_pinmux_dev = &omap4_pinmux_dev;
+ break;
+#endif
+#ifdef SOC_TI_AM335X
+ case CHIP_AM335X:
+ ti_pinmux_dev = &ti_am335x_pinmux_dev;
+ break;
+#endif
+ default:
+ printf("Unknown CPU in pinmux\n");
+ return (ENXIO);
+ }
+
device_set_desc(dev, "TI Pinmux Module");
return (BUS_PROBE_DEFAULT);
diff --git a/sys/arm/ti/ti_pruss.c b/sys/arm/ti/ti_pruss.c
index cbf8050a57b4..8ffb9e078997 100644
--- a/sys/arm/ti/ti_pruss.c
+++ b/sys/arm/ti/ti_pruss.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <machine/frame.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/ti_scm.c b/sys/arm/ti/ti_scm.c
index ae36a9b63a71..bc7861828f16 100644
--- a/sys/arm/ti/ti_scm.c
+++ b/sys/arm/ti/ti_scm.c
@@ -61,11 +61,10 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
-#include <dev/fdt/fdt_common.h>
-#include <dev/fdt/fdt_pinctrl.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/fdt/fdt_pinctrl.h>
#include "ti_scm.h"
diff --git a/sys/arm/ti/ti_sdhci.c b/sys/arm/ti/ti_sdhci.c
index a24e6936a621..ed7f1e72dacc 100644
--- a/sys/arm/ti/ti_sdhci.c
+++ b/sys/arm/ti/ti_sdhci.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -506,10 +505,10 @@ ti_sdhci_attach(device_t dev)
* See if we've got a GPIO-based write detect pin. This is not the
* standard documented property for this, we added it in freebsd.
*/
- if ((OF_getprop(node, "mmchs-wp-gpio-pin", &prop, sizeof(prop))) <= 0)
+ if ((OF_getencprop(node, "mmchs-wp-gpio-pin", &prop, sizeof(prop))) <= 0)
sc->wp_gpio_pin = 0xffffffff;
else
- sc->wp_gpio_pin = fdt32_to_cpu(prop);
+ sc->wp_gpio_pin = prop;
if (sc->wp_gpio_pin != 0xffffffff) {
sc->gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
diff --git a/sys/arm/ti/ti_sdma.c b/sys/arm/ti/ti_sdma.c
index 7e5e9574e4c6..6f3024153fac 100644
--- a/sys/arm/ti/ti_sdma.c
+++ b/sys/arm/ti/ti_sdma.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/ti_spi.c b/sys/arm/ti/ti_spi.c
index e35f365b5e1c..75f3df777101 100644
--- a/sys/arm/ti/ti_spi.c
+++ b/sys/arm/ti/ti_spi.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/ti_wdt.c b/sys/arm/ti/ti_wdt.c
index 2b51cc2d1384..179b783029db 100644
--- a/sys/arm/ti/ti_wdt.c
+++ b/sys/arm/ti/ti_wdt.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <machine/frame.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/usb/omap_ehci.c b/sys/arm/ti/usb/omap_ehci.c
index f7e2057b852c..ea9a01dd8da1 100644
--- a/sys/arm/ti/usb/omap_ehci.c
+++ b/sys/arm/ti/usb/omap_ehci.c
@@ -36,8 +36,8 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/condvar.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/fdt/simplebus.h>
+#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/usb/usb.h>
@@ -58,6 +58,8 @@ __FBSDID("$FreeBSD$");
#include <arm/ti/ti_prcm.h>
#include <arm/ti/usb/omap_usb.h>
+#include <arm/ti/omap4/pandaboard/pandaboard.h>
+
/* EHCI */
#define OMAP_USBHOST_HCCAPBASE 0x0000
#define OMAP_USBHOST_HCSPARAMS 0x0004
@@ -259,7 +261,6 @@ omap_ehci_init(struct omap_ehci_softc *isc)
static int
omap_ehci_probe(device_t dev)
{
-
if (!ofw_bus_status_okay(dev))
return (ENXIO);
@@ -290,9 +291,22 @@ omap_ehci_attach(device_t dev)
{
struct omap_ehci_softc *isc = device_get_softc(dev);
ehci_softc_t *sc = &isc->base;
+#ifdef SOC_OMAP4
+ phandle_t root;
+#endif
int err;
int rid;
+#ifdef SOC_OMAP4
+ /*
+ * If we're running a Pandaboard, run Pandaboard-specific
+ * init code.
+ */
+ root = OF_finddevice("/");
+ if (ofw_bus_node_is_compatible(root, "ti,omap4-panda"))
+ pandaboard_usb_hub_init();
+#endif
+
/* initialise some bus fields */
sc->sc_bus.parent = dev;
sc->sc_bus.devices = sc->sc_devices;
diff --git a/sys/arm/ti/usb/omap_host.c b/sys/arm/ti/usb/omap_host.c
index 326a5b39c388..0bc1118db58b 100644
--- a/sys/arm/ti/usb/omap_host.c
+++ b/sys/arm/ti/usb/omap_host.c
@@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <sys/module.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/fdt/simplebus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/ti/usb/omap_tll.c b/sys/arm/ti/usb/omap_tll.c
index 9bcb7d660a3d..eb3e246a61d6 100644
--- a/sys/arm/ti/usb/omap_tll.c
+++ b/sys/arm/ti/usb/omap_tll.c
@@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <sys/module.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
diff --git a/sys/arm/versatile/pl050.c b/sys/arm/versatile/pl050.c
index c5d8a61372c1..51d22afd3409 100644
--- a/sys/arm/versatile/pl050.c
+++ b/sys/arm/versatile/pl050.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/versatile/sp804.c b/sys/arm/versatile/sp804.c
index de05700dd1c6..894415ba11c7 100644
--- a/sys/arm/versatile/sp804.c
+++ b/sys/arm/versatile/sp804.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -223,8 +222,8 @@ sp804_timer_attach(device_t dev)
sc->sysclk_freq = DEFAULT_FREQUENCY;
/* Get the base clock frequency */
node = ofw_bus_get_node(dev);
- if ((OF_getprop(node, "clock-frequency", &clock, sizeof(clock))) > 0) {
- sc->sysclk_freq = fdt32_to_cpu(clock);
+ if ((OF_getencprop(node, "clock-frequency", &clock, sizeof(clock))) > 0) {
+ sc->sysclk_freq = clock;
}
/* Setup and enable the timer */
diff --git a/sys/arm/versatile/versatile_clcd.c b/sys/arm/versatile/versatile_clcd.c
index 76c6c63d8c50..93f71d53f034 100644
--- a/sys/arm/versatile/versatile_clcd.c
+++ b/sys/arm/versatile/versatile_clcd.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/versatile/versatile_common.c b/sys/arm/versatile/versatile_common.c
index 983b3ce018b5..54d6192eb088 100644
--- a/sys/arm/versatile/versatile_common.c
+++ b/sys/arm/versatile/versatile_common.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
#include <machine/vmparam.h>
@@ -52,7 +53,7 @@ fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
{
- if (!fdt_is_compatible(node, "arm,versatile-vic"))
+ if (!ofw_bus_node_is_compatible(node, "arm,versatile-vic"))
return (ENXIO);
*interrupt = fdt32_to_cpu(intr[0]);
diff --git a/sys/arm/versatile/versatile_machdep.c b/sys/arm/versatile/versatile_machdep.c
index a0c97eeed154..2ce2faf969df 100644
--- a/sys/arm/versatile/versatile_machdep.c
+++ b/sys/arm/versatile/versatile_machdep.c
@@ -51,8 +51,6 @@ __FBSDID("$FreeBSD$");
#include <machine/machdep.h>
#include <machine/platform.h>
-#include <dev/fdt/fdt_common.h>
-
/* Start of address space used for bootstrap map */
#define DEVMAP_BOOTSTRAP_MAP_START 0xE0000000
diff --git a/sys/arm/versatile/versatile_pci.c b/sys/arm/versatile/versatile_pci.c
index 0bc49264c7e1..7db737cc0677 100644
--- a/sys/arm/versatile/versatile_pci.c
+++ b/sys/arm/versatile/versatile_pci.c
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/versatile/versatile_sic.c b/sys/arm/versatile/versatile_sic.c
index 99ffb27a72d6..d695bbfa7548 100644
--- a/sys/arm/versatile/versatile_sic.c
+++ b/sys/arm/versatile/versatile_sic.c
@@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/versatile/versatile_timer.c b/sys/arm/versatile/versatile_timer.c
index c5f6def30c63..b6f508393c8e 100644
--- a/sys/arm/versatile/versatile_timer.c
+++ b/sys/arm/versatile/versatile_timer.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/xilinx/zy7_devcfg.c b/sys/arm/xilinx/zy7_devcfg.c
index 385afd16a33b..74e1cfe87522 100644
--- a/sys/arm/xilinx/zy7_devcfg.c
+++ b/sys/arm/xilinx/zy7_devcfg.c
@@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/stdarg.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/xilinx/zy7_ehci.c b/sys/arm/xilinx/zy7_ehci.c
index 6468faa7ac13..f6e34f774491 100644
--- a/sys/arm/xilinx/zy7_ehci.c
+++ b/sys/arm/xilinx/zy7_ehci.c
@@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/stdarg.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/xilinx/zy7_gpio.c b/sys/arm/xilinx/zy7_gpio.c
index 25d22f87e4dd..a51d60fa3528 100644
--- a/sys/arm/xilinx/zy7_gpio.c
+++ b/sys/arm/xilinx/zy7_gpio.c
@@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/stdarg.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/gpio/gpiobusvar.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
diff --git a/sys/arm/xilinx/zy7_machdep.c b/sys/arm/xilinx/zy7_machdep.c
index 771503d7dd38..472f70c6473c 100644
--- a/sys/arm/xilinx/zy7_machdep.c
+++ b/sys/arm/xilinx/zy7_machdep.c
@@ -44,8 +44,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
-#include <dev/fdt/fdt_common.h>
-
#include <machine/bus.h>
#include <machine/machdep.h>
#include <machine/platform.h>
@@ -92,29 +90,6 @@ platform_devmap_init(void)
return (0);
}
-
-#ifndef INTRNG
-static int
-fdt_gic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
- int *pol)
-{
-
- if (!fdt_is_compatible(node, "arm,gic"))
- return (ENXIO);
-
- *interrupt = fdt32_to_cpu(intr[0]);
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
-
- return (0);
-}
-
-fdt_pic_decode_t fdt_pic_table[] = {
- &fdt_gic_decode_ic,
- NULL
-};
-#endif
-
void
cpu_reset()
{
diff --git a/sys/arm/xilinx/zy7_slcr.c b/sys/arm/xilinx/zy7_slcr.c
index c99d5b0b5aef..bd0311c33203 100644
--- a/sys/arm/xilinx/zy7_slcr.c
+++ b/sys/arm/xilinx/zy7_slcr.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/stdarg.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -621,8 +620,8 @@ zy7_slcr_attach(device_t dev)
/* Derive PLL frequencies from PS_CLK. */
node = ofw_bus_get_node(dev);
- if (OF_getprop(node, "clock-frequency", &cell, sizeof(cell)) > 0)
- ps_clk_frequency = fdt32_to_cpu(cell);
+ if (OF_getencprop(node, "clock-frequency", &cell, sizeof(cell)) > 0)
+ ps_clk_frequency = cell;
else
ps_clk_frequency = ZYNQ_DEFAULT_PS_CLK_FREQUENCY;
diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC
index 4502dc8fb1bf..9b1c42e634f1 100644
--- a/sys/arm64/conf/GENERIC
+++ b/sys/arm64/conf/GENERIC
@@ -121,6 +121,7 @@ device em # Intel PRO/1000 Gigabit Ethernet Family
device igb # Intel PRO/1000 PCIE Server Gigabit Family
device ix # Intel 10Gb Ethernet Family
device msk # Marvell/SysKonnect Yukon II Gigabit Ethernet
+device smc # SMSC LAN91C111
device vnic # Cavium ThunderX NIC
device al_eth # Annapurna Alpine Ethernet NIC
diff --git a/sys/boot/common/commands.c b/sys/boot/common/commands.c
index 9f1d9590e797..2b0e8cbe0aca 100644
--- a/sys/boot/common/commands.c
+++ b/sys/boot/common/commands.c
@@ -497,10 +497,8 @@ command_lsdev(int argc, char *argv[])
pager_open();
for (i = 0; devsw[i] != NULL; i++) {
if (devsw[i]->dv_print != NULL){
- sprintf(line, "%s devices:\n", devsw[i]->dv_name);
- if (pager_output(line))
- break;
- devsw[i]->dv_print(verbose);
+ if (devsw[i]->dv_print(verbose))
+ break;
} else {
sprintf(line, "%s: (unknown)\n", devsw[i]->dv_name);
if (pager_output(line))
diff --git a/sys/boot/common/dev_net.c b/sys/boot/common/dev_net.c
index 7b178af01902..76abb2eb50ba 100644
--- a/sys/boot/common/dev_net.c
+++ b/sys/boot/common/dev_net.c
@@ -332,11 +332,18 @@ net_print(int verbose)
int i, d, cnt;
int ret = 0;
+ if (netif_drivers[0] == NULL)
+ return (ret);
+
+ printf("%s devices:", netdev.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
cnt = 0;
for (d = 0; netif_drivers[d]; d++) {
drv = netif_drivers[d];
for (i = 0; i < drv->netif_nifs; i++) {
- printf("\t%s%d:", "net", cnt++);
+ printf("\t%s%d:", netdev.dv_name, cnt++);
if (verbose) {
printf(" (%s%d)", drv->netif_bname,
drv->netif_ifs[i].dif_unit);
diff --git a/sys/boot/common/install.c b/sys/boot/common/install.c
index 36e7c6484dc5..8c19066894ab 100644
--- a/sys/boot/common/install.c
+++ b/sys/boot/common/install.c
@@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include "bootstrap.h"
-extern struct in_addr rootip;
extern struct in_addr servip;
extern int pkgfs_init(const char *, struct fs_ops *);
@@ -50,6 +49,7 @@ COMMAND_SET(install, "install", "install software package", command_install);
static char *inst_kernel;
static char **inst_modules;
static char *inst_rootfs;
+static char *inst_loader_rc;
static int
setpath(char **what, char *val)
@@ -146,6 +146,8 @@ read_metatags(int fd)
error = setmultipath(&inst_modules, val);
else if (strcmp(tag, "ROOTFS") == 0)
error = setpath(&inst_rootfs, val);
+ else if (strcmp(tag, "LOADER_RC") == 0)
+ error = setpath(&inst_loader_rc, val);
tag = p;
}
@@ -173,6 +175,10 @@ cleanup(void)
free(inst_rootfs);
inst_rootfs = NULL;
}
+ if (inst_loader_rc != NULL) {
+ free(inst_loader_rc);
+ inst_loader_rc = NULL;
+ }
pkgfs_cleanup();
}
@@ -275,6 +281,16 @@ install(char *pkgname)
goto fail;
}
+ /* If there is a loader.rc in the package, execute it */
+ s = (inst_loader_rc == NULL) ? "/loader.rc" : inst_loader_rc;
+ fd = open(s, O_RDONLY);
+ if (fd != -1) {
+ close(fd);
+ error = include(s);
+ if (error == CMD_ERROR)
+ goto fail;
+ }
+
i = 0;
while (inst_modules != NULL && inst_modules[i] != NULL) {
error = mod_loadkld(inst_modules[i], 0, NULL);
@@ -286,7 +302,7 @@ install(char *pkgname)
}
s = (inst_rootfs == NULL) ? "/install.iso" : inst_rootfs;
- if (file_loadraw(s, "mfs_root") == NULL) {
+ if (file_loadraw(s, "mfs_root", 1) == NULL) {
error = errno;
command_errmsg = "cannot load root file system";
goto fail;
diff --git a/sys/boot/common/md.c b/sys/boot/common/md.c
index e5e8a4850dcf..f4469329ca44 100644
--- a/sys/boot/common/md.c
+++ b/sys/boot/common/md.c
@@ -63,7 +63,7 @@ static int md_init(void);
static int md_strategy(void *, int, daddr_t, size_t, size_t, char *, size_t *);
static int md_open(struct open_file *, ...);
static int md_close(struct open_file *);
-static void md_print(int);
+static int md_print(int);
struct devsw md_dev = {
"md",
@@ -143,9 +143,14 @@ md_close(struct open_file *f)
return ((dev->d_unit != 0) ? ENXIO : 0);
}
-static void
+static int
md_print(int verbose)
{
- printf("MD (%u bytes)\n", MD_IMAGE_SIZE);
+ printf("%s devices:", md_dev.dv_name);
+ if (pager_output("\n") != 0)
+ return (1);
+
+ printf("MD (%u bytes)", MD_IMAGE_SIZE);
+ return (pager_output("\n"));
}
diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c
index 8d7db1f63f14..1207088d8682 100644
--- a/sys/boot/efi/libefi/efinet.c
+++ b/sys/boot/efi/libefi/efinet.c
@@ -353,6 +353,10 @@ efinet_dev_print(int verbose)
EFI_HANDLE h;
int unit, ret = 0;
+ printf("%s devices:", efinet_dev.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
for (unit = 0, h = efi_find_handle(&efinet_dev, 0);
h != NULL; h = efi_find_handle(&efinet_dev, ++unit)) {
printf(" %s%d:", efinet_dev.dv_name, unit);
diff --git a/sys/boot/efi/libefi/efipart.c b/sys/boot/efi/libefi/efipart.c
index cba94de9d27d..5a993812bce0 100644
--- a/sys/boot/efi/libefi/efipart.c
+++ b/sys/boot/efi/libefi/efipart.c
@@ -172,6 +172,10 @@ efipart_print(int verbose)
u_int unit;
int ret = 0;
+ printf("%s devices:", efipart_dev.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
for (unit = 0, h = efi_find_handle(&efipart_dev, 0);
h != NULL; h = efi_find_handle(&efipart_dev, ++unit)) {
snprintf(line, sizeof(line), " %s%d:",
diff --git a/sys/boot/fdt/dts/arm/sun7i-a20-hdmi.dtsi b/sys/boot/fdt/dts/arm/sun7i-a20-hdmi.dtsi
index 2567be51da61..c83d6a2c1d99 100644
--- a/sys/boot/fdt/dts/arm/sun7i-a20-hdmi.dtsi
+++ b/sys/boot/fdt/dts/arm/sun7i-a20-hdmi.dtsi
@@ -28,25 +28,11 @@
/ {
clocks {
- pll3: clk@01c20010 {
- #clock-cells = <1>;
- compatible = "allwinner,sun4i-a10-pll3-clk";
- reg = <0x01c20010 0x4>;
- clock-output-names = "pll3-1x", "pll3-2x";
- };
-
- pll7: clk@01c20030 {
- #clock-cells = <1>;
- compatible = "allwinner,sun4i-a10-pll3-clk";
- reg = <0x01c20030 0x4>;
- clock-output-names = "pll7-1x", "pll7-2x";
- };
-
hdmi_clk: clk@01c20150 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-hdmi-clk";
reg = <0x01c20150 0x4>;
- clocks = <&pll3 0>, <&pll7 0>, <&pll3 1>, <&pll7 1>;
+ clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
clock-output-names = "hdmi";
};
@@ -55,7 +41,7 @@
#reset-cells = <0>;
compatible = "allwinner,sun4i-a10-lcd-ch0-clk";
reg = <0x01c20118 0x4>;
- clocks = <&pll3 0>, <&pll7 0>, <&pll3 1>, <&pll6 2>;
+ clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll6 2>;
clock-output-names = "lcd0_ch0";
};
@@ -63,7 +49,7 @@
#clock-cells = <1>;
compatible = "allwinner,sun4i-a10-lcd-ch1-clk";
reg = <0x01c2012c 0x4>;
- clocks = <&pll3 0>, <&pll7 0>, <&pll3 1>, <&pll7 1>;
+ clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
clock-output-names = "lcd0_ch1_sclk1",
"lcd0_ch1_sclk2";
};
@@ -73,7 +59,7 @@
#reset-cells = <0>;
compatible = "allwinner,sun4i-a10-de-be-clk";
reg = <0x01c20104 0x4>;
- clocks = <&pll3 0>, <&pll7 0>, <&pll5 1>;
+ clocks = <&pll3>, <&pll7>, <&pll5 1>;
clock-output-names = "de_be0";
};
};
diff --git a/sys/boot/fdt/dts/powerpc/p2041rdb.dts b/sys/boot/fdt/dts/powerpc/p2041rdb.dts
index aa5af072e768..3ce2e60096cc 100644
--- a/sys/boot/fdt/dts/powerpc/p2041rdb.dts
+++ b/sys/boot/fdt/dts/powerpc/p2041rdb.dts
@@ -442,47 +442,6 @@
};
};
- fsl,dpaa {
- compatible = "fsl,p2041-dpaa", "fsl,dpaa";
-
- ethernet@0 {
- compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet0>;
- status = "okay";
- };
- ethernet@1 {
- compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet1>;
- status = "okay";
- };
- ethernet@2 {
- compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet2>;
- status = "okay";
- };
- ethernet@3 {
- compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet3>;
- status = "okay";
- };
- ethernet@4 {
- compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet4>;
- status = "okay";
- };
- ethernet@5 {
- compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet5>;
- status = "okay";
- };
- };
-
chosen {
stdin = "serial0";
stdout = "serial0";
diff --git a/sys/boot/fdt/dts/powerpc/p2041si.dtsi b/sys/boot/fdt/dts/powerpc/p2041si.dtsi
index 9db01fa62ca9..41eb1dd74523 100644
--- a/sys/boot/fdt/dts/powerpc/p2041si.dtsi
+++ b/sys/boot/fdt/dts/powerpc/p2041si.dtsi
@@ -208,7 +208,7 @@
bman-portals@ff4000000 {
#address-cells = <0x1>;
#size-cells = <0x1>;
- compatible = "bman-portals";
+ compatible = "fsl,bman-portals";
ranges = <0x0 0xf 0xfde00000 0x200000>;
bman-portal@0 {
cell-index = <0x0>;
@@ -281,7 +281,7 @@
qman-portals@ff4200000 {
#address-cells = <0x1>;
#size-cells = <0x1>;
- compatible = "qman-portals";
+ compatible = "fsl,qman-portals";
ranges = <0x0 0xf 0xfdc00000 0x200000>;
qportal0: qman-portal@0 {
cell-index = <0x0>;
@@ -913,8 +913,8 @@
pme: pme@316000 {
compatible = "fsl,pme";
reg = <0x316000 0x10000>;
- /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
- /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
+ /* "fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
+ /* "fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
interrupts = <16 2 1 5>;
};
@@ -923,16 +923,16 @@
reg = <0x318000 0x1000>;
interrupts = <16 2 1 3>;
/* Commented out, use default allocation */
- /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
- /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
+ /* "fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
+ /* "fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
};
bman: bman@31a000 {
compatible = "fsl,p2041-bman", "fsl,bman";
reg = <0x31a000 0x1000>;
interrupts = <16 2 1 2>;
- /* Same as fsl,qman-*, use default allocation */
- /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
+ /* Same as "fsl,qman-*, use default allocation */
+ /* "fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
};
fman0: fman@400000 {
@@ -983,27 +983,27 @@
fman0_rx0: port@88000 {
cell-index = <0>;
- compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x88000 0x1000>;
};
fman0_rx1: port@89000 {
cell-index = <1>;
- compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x89000 0x1000>;
};
fman0_rx2: port@8a000 {
cell-index = <2>;
- compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x8a000 0x1000>;
};
fman0_rx3: port@8b000 {
cell-index = <3>;
- compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x8b000 0x1000>;
};
fman0_rx4: port@8c000 {
cell-index = <4>;
- compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x8c000 0x1000>;
};
fman0_rx5: port@90000 {
@@ -1020,31 +1020,31 @@
};
fman0_tx0: port@a8000 {
cell-index = <0>;
- compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xa8000 0x1000>;
fsl,qman-channel-id = <0x41>;
};
fman0_tx1: port@a9000 {
cell-index = <1>;
- compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xa9000 0x1000>;
fsl,qman-channel-id = <0x42>;
};
fman0_tx2: port@aa000 {
cell-index = <2>;
- compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xaa000 0x1000>;
fsl,qman-channel-id = <0x43>;
};
fman0_tx3: port@ab000 {
cell-index = <3>;
- compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xab000 0x1000>;
fsl,qman-channel-id = <0x44>;
};
fman0_tx4: port@ac000 {
cell-index = <4>;
- compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xac000 0x1000>;
fsl,qman-channel-id = <0x45>;
};
@@ -1093,7 +1093,7 @@
enet0: ethernet@e0000 {
cell-index = <0>;
- compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe0000 0x1000>;
fsl,port-handles = <&fman0_rx0 &fman0_tx0>;
};
@@ -1108,7 +1108,7 @@
enet1: ethernet@e2000 {
cell-index = <1>;
- compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe2000 0x1000>;
fsl,port-handles = <&fman0_rx1 &fman0_tx1>;
};
@@ -1123,7 +1123,7 @@
enet2: ethernet@e4000 {
cell-index = <2>;
- compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe4000 0x1000>;
fsl,port-handles = <&fman0_rx2 &fman0_tx2>;
};
@@ -1138,7 +1138,7 @@
enet3: ethernet@e6000 {
cell-index = <3>;
- compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe6000 0x1000>;
fsl,port-handles = <&fman0_rx3 &fman0_tx3>;
};
@@ -1153,7 +1153,7 @@
enet4: ethernet@e8000 {
cell-index = <4>;
- compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe8000 0x1000>;
fsl,port-handles = <&fman0_rx4 &fman0_tx4>;
};
@@ -1168,7 +1168,7 @@
enet5: ethernet@f0000 {
cell-index = <0>;
- compatible = "fsl,p2041-fman-10g-mac", "fsl,fman-10g-mac";
+ compatible = "fsl,p2041-fman-10g-mac", "fsl,fman-10g-mac", "fsl,fman-xgec";
reg = <0xf0000 0x1000>;
fsl,port-handles = <&fman0_rx5 &fman0_tx5>;
};
diff --git a/sys/boot/fdt/dts/powerpc/p3041ds.dts b/sys/boot/fdt/dts/powerpc/p3041ds.dts
index 70787e432765..bcc9ff3112b5 100644
--- a/sys/boot/fdt/dts/powerpc/p3041ds.dts
+++ b/sys/boot/fdt/dts/powerpc/p3041ds.dts
@@ -539,47 +539,6 @@
};
};
- fsl,dpaa {
- compatible = "fsl,p3041-dpaa", "fsl,dpaa";
-
- ethernet@0 {
- compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet0>;
- status="okay";
- };
- ethernet@1 {
- compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet1>;
- status = "disabled";
- };
- ethernet@2 {
- compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet2>;
- status = "disabled";
- };
- ethernet@3 {
- compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet3>;
- status = "disabled";
- };
- ethernet@4 {
- compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet4>;
- status = "okay";
- };
- ethernet@5 {
- compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet5>;
- status = "disabled";
- };
- };
-
chosen {
stdin = "serial0";
stdout = "serial0";
diff --git a/sys/boot/fdt/dts/powerpc/p3041si.dtsi b/sys/boot/fdt/dts/powerpc/p3041si.dtsi
index 3335e48d4702..368cd6272bfb 100644
--- a/sys/boot/fdt/dts/powerpc/p3041si.dtsi
+++ b/sys/boot/fdt/dts/powerpc/p3041si.dtsi
@@ -209,7 +209,7 @@
bman-portals@ff4000000 {
#address-cells = <0x1>;
#size-cells = <0x1>;
- compatible = "bman-portals";
+ compatible = "fsl,bman-portals";
ranges = <0x0 0xf 0xfde00000 0x200000>;
bman-portal@0 {
cell-index = <0x0>;
@@ -282,7 +282,7 @@
qman-portals@ff4200000 {
#address-cells = <0x1>;
#size-cells = <0x1>;
- compatible = "qman-portals";
+ compatible = "fsl,qman-portals";
ranges = <0x0 0xf 0xfdc00000 0x200000>;
qportal0: qman-portal@0 {
cell-index = <0x0>;
@@ -915,8 +915,8 @@
pme: pme@316000 {
compatible = "fsl,pme";
reg = <0x316000 0x10000>;
- /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
- /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
+ /* "fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
+ /* "fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
interrupts = <16 2 1 5>;
};
@@ -925,16 +925,16 @@
reg = <0x318000 0x1000>;
interrupts = <16 2 1 3>;
/* Commented out, use default allocation */
- /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
- /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
+ /* "fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
+ /* "fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
};
bman: bman@31a000 {
compatible = "fsl,p3041-bman", "fsl,bman";
reg = <0x31a000 0x1000>;
interrupts = <16 2 1 2>;
- /* Same as fsl,qman-*, use default allocation */
- /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
+ /* Same as "fsl,qman-*, use default allocation */
+ /* "fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
};
fman0: fman@400000 {
@@ -985,27 +985,27 @@
fman0_rx0: port@88000 {
cell-index = <0>;
- compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x88000 0x1000>;
};
fman0_rx1: port@89000 {
cell-index = <1>;
- compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x89000 0x1000>;
};
fman0_rx2: port@8a000 {
cell-index = <2>;
- compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x8a000 0x1000>;
};
fman0_rx3: port@8b000 {
cell-index = <3>;
- compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x8b000 0x1000>;
};
fman0_rx4: port@8c000 {
cell-index = <4>;
- compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x8c000 0x1000>;
};
fman0_rx5: port@90000 {
@@ -1022,31 +1022,31 @@
};
fman0_tx0: port@a8000 {
cell-index = <0>;
- compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xa8000 0x1000>;
fsl,qman-channel-id = <0x41>;
};
fman0_tx1: port@a9000 {
cell-index = <1>;
- compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xa9000 0x1000>;
fsl,qman-channel-id = <0x42>;
};
fman0_tx2: port@aa000 {
cell-index = <2>;
- compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xaa000 0x1000>;
fsl,qman-channel-id = <0x43>;
};
fman0_tx3: port@ab000 {
cell-index = <3>;
- compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xab000 0x1000>;
fsl,qman-channel-id = <0x44>;
};
fman0_tx4: port@ac000 {
cell-index = <4>;
- compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xac000 0x1000>;
fsl,qman-channel-id = <0x45>;
};
@@ -1095,7 +1095,8 @@
enet0: ethernet@e0000 {
cell-index = <0>;
- compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p3041-fman-1g-mac",
+ "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe0000 0x1000>;
fsl,port-handles = <&fman0_rx0 &fman0_tx0>;
ptimer-handle = <&ptp_timer0>;
@@ -1111,7 +1112,8 @@
enet1: ethernet@e2000 {
cell-index = <1>;
- compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p3041-fman-1g-mac",
+ "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe2000 0x1000>;
fsl,port-handles = <&fman0_rx1 &fman0_tx1>;
ptimer-handle = <&ptp_timer0>;
@@ -1127,7 +1129,8 @@
enet2: ethernet@e4000 {
cell-index = <2>;
- compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p3041-fman-1g-mac",
+ "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe4000 0x1000>;
fsl,port-handles = <&fman0_rx2 &fman0_tx2>;
ptimer-handle = <&ptp_timer0>;
@@ -1143,7 +1146,8 @@
enet3: ethernet@e6000 {
cell-index = <3>;
- compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p3041-fman-1g-mac",
+ "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe6000 0x1000>;
fsl,port-handles = <&fman0_rx3 &fman0_tx3>;
};
@@ -1158,7 +1162,8 @@
enet4: ethernet@e8000 {
cell-index = <4>;
- compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p3041-fman-1g-mac",
+ "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe8000 0x1000>;
fsl,port-handles = <&fman0_rx4 &fman0_tx4>;
ptimer-handle = <&ptp_timer0>;
@@ -1174,7 +1179,8 @@
enet5: ethernet@f0000 {
cell-index = <0>;
- compatible = "fsl,p3041-fman-10g-mac", "fsl,fman-10g-mac";
+ compatible = "fsl,p3041-fman-10g-mac",
+ "fsl,fman-10g-mac", "fsl,fman-xgec";
reg = <0xf0000 0x1000>;
fsl,port-handles = <&fman0_rx5 &fman0_tx5>;
};
diff --git a/sys/boot/fdt/dts/powerpc/p5020ds.dts b/sys/boot/fdt/dts/powerpc/p5020ds.dts
index cb070457924e..3e0d92fbd83e 100644
--- a/sys/boot/fdt/dts/powerpc/p5020ds.dts
+++ b/sys/boot/fdt/dts/powerpc/p5020ds.dts
@@ -535,47 +535,6 @@
};
};
- fsl,dpaa {
- compatible = "fsl,p5020-dpaa", "fsl,dpaa";
-
- ethernet@0 {
- compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet0>;
- status = "okay";
- };
- ethernet@1 {
- compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet1>;
- status = "disabled";
- };
- ethernet@2 {
- compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet2>;
- status = "disabled";
- };
- ethernet@3 {
- compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet3>;
- status = "disabled";
- };
- ethernet@4 {
- compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet4>;
- status = "okay";
- };
- ethernet@5 {
- compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
- fsl,qman-channel = <&qpool1>;
- fsl,fman-mac = <&enet5>;
- status = "disabled";
- };
- };
-
chosen {
stdin = "serial0";
stdout = "serial0";
diff --git a/sys/boot/fdt/dts/powerpc/p5020si.dtsi b/sys/boot/fdt/dts/powerpc/p5020si.dtsi
index 27699cbc7e03..afed942a2b96 100644
--- a/sys/boot/fdt/dts/powerpc/p5020si.dtsi
+++ b/sys/boot/fdt/dts/powerpc/p5020si.dtsi
@@ -194,7 +194,7 @@
bman-portals@ff4000000 {
#address-cells = <0x1>;
#size-cells = <0x1>;
- compatible = "bman-portals";
+ compatible = "fsl,bman-portals";
ranges = <0x0 0xf 0xfde00000 0x200000>;
bman-portal@0 {
cell-index = <0x0>;
@@ -267,7 +267,7 @@
qman-portals@ff4200000 {
#address-cells = <0x1>;
#size-cells = <0x1>;
- compatible = "qman-portals";
+ compatible = "fsl,qman-portals";
ranges = <0x0 0xf 0xfdc00000 0x200000>;
qportal0: qman-portal@0 {
cell-index = <0x0>;
@@ -960,8 +960,8 @@
pme: pme@316000 {
compatible = "fsl,pme";
reg = <0x316000 0x10000>;
- /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
- /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
+ /* "fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
+ /* "fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
interrupts = <16 2 1 5>;
};
@@ -970,16 +970,16 @@
reg = <0x318000 0x1000>;
interrupts = <16 2 1 3>;
/* Commented out, use default allocation */
- /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
- /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
+ /* "fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
+ /* "fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
};
bman: bman@31a000 {
compatible = "fsl,p5020-bman", "fsl,bman";
reg = <0x31a000 0x1000>;
interrupts = <16 2 1 2>;
- /* Same as fsl,qman-*, use default allocation */
- /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
+ /* Same as "fsl,qman-*, use default allocation */
+ /* "fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
};
fman0: fman@400000 {
@@ -1030,27 +1030,27 @@
fman0_rx0: port@88000 {
cell-index = <0>;
- compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x88000 0x1000>;
};
fman0_rx1: port@89000 {
cell-index = <1>;
- compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x89000 0x1000>;
};
fman0_rx2: port@8a000 {
cell-index = <2>;
- compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x8a000 0x1000>;
};
fman0_rx3: port@8b000 {
cell-index = <3>;
- compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x8b000 0x1000>;
};
fman0_rx4: port@8c000 {
cell-index = <4>;
- compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx";
reg = <0x8c000 0x1000>;
};
fman0_rx5: port@90000 {
@@ -1067,31 +1067,31 @@
};
fman0_tx0: port@a8000 {
cell-index = <0>;
- compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xa8000 0x1000>;
fsl,qman-channel-id = <0x41>;
};
fman0_tx1: port@a9000 {
cell-index = <1>;
- compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xa9000 0x1000>;
fsl,qman-channel-id = <0x42>;
};
fman0_tx2: port@aa000 {
cell-index = <2>;
- compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xaa000 0x1000>;
fsl,qman-channel-id = <0x43>;
};
fman0_tx3: port@ab000 {
cell-index = <3>;
- compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xab000 0x1000>;
fsl,qman-channel-id = <0x44>;
};
fman0_tx4: port@ac000 {
cell-index = <4>;
- compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx";
reg = <0xac000 0x1000>;
fsl,qman-channel-id = <0x45>;
};
@@ -1140,7 +1140,7 @@
enet0: ethernet@e0000 {
cell-index = <0>;
- compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe0000 0x1000>;
fsl,port-handles = <&fman0_rx0 &fman0_tx0>;
ptimer-handle = <&ptp_timer0>;
@@ -1156,7 +1156,7 @@
enet1: ethernet@e2000 {
cell-index = <1>;
- compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe2000 0x1000>;
fsl,port-handles = <&fman0_rx1 &fman0_tx1>;
ptimer-handle = <&ptp_timer0>;
@@ -1172,7 +1172,7 @@
enet2: ethernet@e4000 {
cell-index = <2>;
- compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe4000 0x1000>;
fsl,port-handles = <&fman0_rx2 &fman0_tx2>;
ptimer-handle = <&ptp_timer0>;
@@ -1188,7 +1188,7 @@
enet3: ethernet@e6000 {
cell-index = <3>;
- compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe6000 0x1000>;
fsl,port-handles = <&fman0_rx3 &fman0_tx3>;
ptimer-handle = <&ptp_timer0>;
@@ -1204,7 +1204,7 @@
enet4: ethernet@e8000 {
cell-index = <4>;
- compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac";
+ compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec";
reg = <0xe8000 0x1000>;
fsl,port-handles = <&fman0_rx4 &fman0_tx4>;
ptimer-handle = <&ptp_timer0>;
@@ -1220,7 +1220,7 @@
enet5: ethernet@f0000 {
cell-index = <0>;
- compatible = "fsl,p5020-fman-10g-mac", "fsl,fman-10g-mac";
+ compatible = "fsl,p5020-fman-10g-mac", "fsl,fman-10g-mac", "fsl,fman-xgec";
reg = <0xf0000 0x1000>;
fsl,port-handles = <&fman0_rx5 &fman0_tx5>;
};
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index 69a4fcde2132..d17d33580db6 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -312,6 +312,7 @@ if_axe_load="NO" # ASIX Electronics AX88172 USB Ethernet
if_bce_load="NO" # Broadcom NetXtreme II Gigabit Ethernet
if_bfe_load="NO" # Broadcom BCM4401
if_bge_load="NO" # Broadcom BCM570x PCI Gigabit Ethernet
+if_bnxt_load="NO" # Broadcom NetXtreme-C/NetXtreme-E
if_bridge_load="NO" # if_bridge(4) devices
if_bwi_load="NO" # Broadcom BCM53xx IEEE 802.11b/g wireness NICs
if_bwn_load="NO" # Broadcom BCM43xx IEEE 802.11 wireless NICs
diff --git a/sys/boot/i386/libfirewire/firewire.c b/sys/boot/i386/libfirewire/firewire.c
index fea61f3bad96..f29759448205 100644
--- a/sys/boot/i386/libfirewire/firewire.c
+++ b/sys/boot/i386/libfirewire/firewire.c
@@ -155,6 +155,10 @@ fw_print(int verbose)
int i, ret = 0;
struct fwohci_softc *sc;
+ printf("%s devices:", fwohci.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
for (i = 0; i < MAX_OHCI; i ++) {
sc = &fwinfo[i];
if (sc->state == FWOHCI_STATE_DEAD)
diff --git a/sys/boot/i386/libi386/bioscd.c b/sys/boot/i386/libi386/bioscd.c
index 776ddfa65feb..37cd6d2aa4c5 100644
--- a/sys/boot/i386/libi386/bioscd.c
+++ b/sys/boot/i386/libi386/bioscd.c
@@ -183,6 +183,13 @@ bc_print(int verbose)
char line[80];
int i, ret = 0;
+ if (nbcinfo == 0)
+ return (0);
+
+ printf("%s devices:", bioscd.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
for (i = 0; i < nbcinfo; i++) {
snprintf(line, sizeof(line), " cd%d: Device 0x%x\n", i,
bcinfo[i].bc_sp.sp_devicespec);
diff --git a/sys/boot/i386/libi386/biosdisk.c b/sys/boot/i386/libi386/biosdisk.c
index 0af0c2a4c818..fa59234e0d3c 100644
--- a/sys/boot/i386/libi386/biosdisk.c
+++ b/sys/boot/i386/libi386/biosdisk.c
@@ -328,6 +328,13 @@ bd_print(int verbose)
struct disk_devdesc dev;
int i, ret = 0;
+ if (nbdinfo == 0)
+ return (0);
+
+ printf("%s devices:", biosdisk.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
for (i = 0; i < nbdinfo; i++) {
snprintf(line, sizeof(line),
" disk%d: BIOS drive %c (%ju X %u):\n", i,
diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c
index a246e8356247..7f27ba4a674a 100644
--- a/sys/boot/i386/libi386/pxe.c
+++ b/sys/boot/i386/libi386/pxe.c
@@ -389,6 +389,9 @@ pxe_print(int verbose)
if (pxe_call == NULL)
return (0);
+ printf("%s devices:", pxedisk.dv_name);
+ if (pager_output("\n") != 0)
+ return (1);
if (verbose) {
snprintf(line, sizeof(line), " pxe0: %s:%s\n",
inet_ntoa(rootip), rootpath);
diff --git a/sys/boot/mips/beri/loader/beri_disk_cfi.c b/sys/boot/mips/beri/loader/beri_disk_cfi.c
index 7a84cc648b44..a9695e2d9297 100644
--- a/sys/boot/mips/beri/loader/beri_disk_cfi.c
+++ b/sys/boot/mips/beri/loader/beri_disk_cfi.c
@@ -119,6 +119,10 @@ beri_cfi_disk_print(int verbose)
char line[80];
int ret;
+ printf("%s devices:", beri_cfi_disk.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
snprintf(line, sizeof(line), " cfi%d CFI flash device\n", 0);
ret = pager_output(line);
if (ret != 0)
diff --git a/sys/boot/mips/beri/loader/beri_disk_sdcard.c b/sys/boot/mips/beri/loader/beri_disk_sdcard.c
index e1a2e87d11f0..c07ba75c1db1 100644
--- a/sys/boot/mips/beri/loader/beri_disk_sdcard.c
+++ b/sys/boot/mips/beri/loader/beri_disk_sdcard.c
@@ -118,13 +118,17 @@ beri_sdcard_disk_close(struct open_file *f)
return (disk_close(dev));
}
-static void
+static int
beri_sdcard_disk_print(int verbose)
{
struct disk_devdesc dev;
char line[80];
int ret;
+ printf("%s devices:", beri_sdcard_disk.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
snprintf(line, sizeof(line), " sdcard%d Altera SD card drive\n", 0);
ret = pager_output(line);
if (ret != 0)
diff --git a/sys/boot/pc98/libpc98/bioscd.c b/sys/boot/pc98/libpc98/bioscd.c
index 6e520138400b..9cdc5673bfd3 100644
--- a/sys/boot/pc98/libpc98/bioscd.c
+++ b/sys/boot/pc98/libpc98/bioscd.c
@@ -179,6 +179,13 @@ bc_print(int verbose)
char line[80];
int i, ret = 0;
+ if (nbcinfo == 0)
+ return (0);
+
+ printf("%s devices:", bioscd.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
for (i = 0; i < nbcinfo; i++) {
sprintf(line, " cd%d: Device 0x%x\n", i,
bcinfo[i].bc_sp.sp_devicespec);
diff --git a/sys/boot/pc98/libpc98/biosdisk.c b/sys/boot/pc98/libpc98/biosdisk.c
index 6ecfa4912a62..3163019c2b9b 100644
--- a/sys/boot/pc98/libpc98/biosdisk.c
+++ b/sys/boot/pc98/libpc98/biosdisk.c
@@ -258,6 +258,13 @@ bd_print(int verbose)
struct open_disk *od;
struct pc98_partition *dptr;
+ if (nbdinfo == 0)
+ return (0);
+
+ printf("%s devices:", biosdisk.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
for (i = 0; i < nbdinfo; i++) {
snprintf(line, sizeof(line), " disk%d: BIOS drive %c:\n",
i, 'A' + i);
diff --git a/sys/boot/uboot/lib/disk.c b/sys/boot/uboot/lib/disk.c
index c0d187d1f962..474d4aa31f7e 100644
--- a/sys/boot/uboot/lib/disk.c
+++ b/sys/boot/uboot/lib/disk.c
@@ -245,6 +245,13 @@ stor_print(int verbose)
static char line[80];
int i, ret = 0;
+ if (stor_info_no == 0)
+ return (ret);
+
+ printf("%s devices:", uboot_storage.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
for (i = 0; i < stor_info_no; i++) {
dev.d_dev = &uboot_storage;
dev.d_unit = i;
diff --git a/sys/boot/usb/storage/umass_loader.c b/sys/boot/usb/storage/umass_loader.c
index e6e38bfe9e2a..9ecd4b2e162e 100644
--- a/sys/boot/usb/storage/umass_loader.c
+++ b/sys/boot/usb/storage/umass_loader.c
@@ -175,6 +175,10 @@ umass_disk_print(int verbose)
{
struct disk_devdesc dev;
+ printf("%s devices:", umass_disk.dv_name);
+ if (pager_output("\n") != 0)
+ return (1);
+
memset(&dev, 0, sizeof(dev));
ret = pager_output(" umass0 UMASS device\n");
diff --git a/sys/boot/userboot/userboot/host.c b/sys/boot/userboot/userboot/host.c
index dca2f341ba69..e69d2d31bfc1 100644
--- a/sys/boot/userboot/userboot/host.c
+++ b/sys/boot/userboot/userboot/host.c
@@ -139,6 +139,10 @@ host_dev_print(int verbose)
{
char line[80];
+ printf("%s devices:", host_dev.dv_name);
+ if (pager_output("\n") != 0)
+ return (1);
+
snprintf(line, sizeof(line), " host%d: Host filesystem\n", 0);
return (pager_output(line));
}
diff --git a/sys/boot/userboot/userboot/userboot_disk.c b/sys/boot/userboot/userboot/userboot_disk.c
index 7c0c36820a90..ecd933b9c316 100644
--- a/sys/boot/userboot/userboot/userboot_disk.c
+++ b/sys/boot/userboot/userboot/userboot_disk.c
@@ -123,6 +123,13 @@ userdisk_print(int verbose)
char line[80];
int i, ret = 0;
+ if (userdisk_maxunit == 0)
+ return (0);
+
+ printf("%s devices:", userboot_disk.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
for (i = 0; i < userdisk_maxunit; i++) {
snprintf(line, sizeof(line),
" disk%d: Guest drive image\n", i);
diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c
index 3efa429e84a4..602db44aa977 100644
--- a/sys/boot/zfs/zfs.c
+++ b/sys/boot/zfs/zfs.c
@@ -521,6 +521,13 @@ zfs_dev_print(int verbose)
char line[80];
int ret = 0;
+ if (STAILQ_EMPTY(&zfs_pools))
+ return (0);
+
+ printf("%s devices:", zfs_dev.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
if (verbose) {
return (spa_all_status());
}
diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c
index 5f05c35587af..8729a7517d1c 100644
--- a/sys/boot/zfs/zfsimpl.c
+++ b/sys/boot/zfs/zfsimpl.c
@@ -1049,8 +1049,10 @@ vdev_probe(vdev_phys_read_t *read, void *read_priv, spa_t **spap)
STAILQ_FOREACH(pool_vdev, &spa->spa_vdevs, v_childlink)
if (top_vdev == pool_vdev)
break;
- if (!pool_vdev && top_vdev)
+ if (!pool_vdev && top_vdev) {
+ top_vdev->spa = spa;
STAILQ_INSERT_TAIL(&spa->spa_vdevs, top_vdev, v_childlink);
+ }
/*
* We should already have created an incomplete vdev for this
diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c
index ddb565830ae0..cb7205e3331b 100644
--- a/sys/cam/scsi/scsi_xpt.c
+++ b/sys/cam/scsi/scsi_xpt.c
@@ -1626,8 +1626,8 @@ probe_device_check:
sizeof(struct scsi_inquiry_data));
if (have_serialnum)
- MD5Update(&context, serial_buf->serial_num,
- serial_buf->length);
+ MD5Update(&context, path->device->serial_num,
+ path->device->serial_num_len);
MD5Final(digest, &context);
if (bcmp(softc->digest, digest, 16) == 0)
diff --git a/sys/cddl/compat/opensolaris/sys/vnode.h b/sys/cddl/compat/opensolaris/sys/vnode.h
index e7a92ae9957b..d15cd88c193a 100644
--- a/sys/cddl/compat/opensolaris/sys/vnode.h
+++ b/sys/cddl/compat/opensolaris/sys/vnode.h
@@ -75,8 +75,7 @@ vn_is_readonly(vnode_t *vp)
#define vn_mountedvfs(vp) ((vp)->v_mountedhere)
#define vn_has_cached_data(vp) \
((vp)->v_object != NULL && \
- ((vp)->v_object->resident_page_count > 0 || \
- !vm_object_cache_is_empty((vp)->v_object)))
+ (vp)->v_object->resident_page_count > 0)
#define vn_exists(vp) do { } while (0)
#define vn_invalid(vp) do { } while (0)
#define vn_renamepath(tdvp, svp, tnm, lentnm) do { } while (0)
diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
index 8ef31211fe1f..27d62d1f0134 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
@@ -6042,22 +6042,6 @@ inetout: regs[rd] = (uintptr_t)end + 1;
break;
}
#endif
-
- case DIF_SUBR_TYPEREF: {
- uintptr_t size = 4 * sizeof(uintptr_t);
- uintptr_t *typeref = (uintptr_t *) P2ROUNDUP(mstate->dtms_scratch_ptr, sizeof(uintptr_t));
- size_t scratch_size = ((uintptr_t) typeref - mstate->dtms_scratch_ptr) + size;
-
- /* address, num_elements, type_str, type_len */
- typeref[0] = tupregs[0].dttk_value;
- typeref[1] = tupregs[1].dttk_value;
- typeref[2] = tupregs[2].dttk_value;
- typeref[3] = tupregs[3].dttk_value;
-
- regs[rd] = (uintptr_t) typeref;
- mstate->dtms_scratch_ptr += scratch_size;
- break;
- }
}
}
@@ -7707,66 +7691,6 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
break;
}
- case DTRACEACT_PRINTT: {
- /* The DIF returns a 'typeref'. */
- uintptr_t *typeref = (uintptr_t *)(uintptr_t) val;
- char c = '\0' + 1;
- size_t s;
-
- /*
- * Get the type string length and round it
- * up so that the data that follows is
- * aligned for easy access.
- */
- size_t typs = strlen((char *) typeref[2]) + 1;
- typs = roundup(typs, sizeof(uintptr_t));
-
- /*
- *Get the size from the typeref using the
- * number of elements and the type size.
- */
- size = typeref[1] * typeref[3];
-
- /*
- * Check if the size exceeds the allocated
- * buffer size.
- */
- if (size + typs + 2 * sizeof(uintptr_t) > dp->dtdo_rtype.dtdt_size) {
- /* Flag a drop! */
- *flags |= CPU_DTRACE_DROP;
-
- }
-
- /* Store the size in the buffer first. */
- DTRACE_STORE(uintptr_t, tomax,
- valoffs, size);
- valoffs += sizeof(uintptr_t);
-
- /* Store the type size in the buffer. */
- DTRACE_STORE(uintptr_t, tomax,
- valoffs, typeref[3]);
- valoffs += sizeof(uintptr_t);
-
- val = typeref[2];
-
- for (s = 0; s < typs; s++) {
- if (c != '\0')
- c = dtrace_load8(val++);
-
- DTRACE_STORE(uint8_t, tomax,
- valoffs++, c);
- }
-
- /*
- * Reset to the memory address rather than
- * the typeref array, then let the BYREF
- * code below do the work to store the
- * memory data in the buffer.
- */
- val = typeref[0];
- break;
- }
-
case DTRACEACT_CHILL:
if (dtrace_priv_kernel_destructive(state))
dtrace_action_chill(&mstate, val);
@@ -10342,12 +10266,12 @@ dtrace_difo_validate_helper(dtrace_difo_t *dp)
subr == DIF_SUBR_NTOHS ||
subr == DIF_SUBR_NTOHL ||
subr == DIF_SUBR_NTOHLL ||
- subr == DIF_SUBR_MEMREF ||
-#ifndef illumos
- subr == DIF_SUBR_MEMSTR ||
-#endif
- subr == DIF_SUBR_TYPEREF)
+ subr == DIF_SUBR_MEMREF)
break;
+#ifdef __FreeBSD__
+ if (subr == DIF_SUBR_MEMSTR)
+ break;
+#endif
err += efunc(pc, "invalid subr %u\n", subr);
break;
@@ -11647,10 +11571,6 @@ dtrace_ecb_action_add(dtrace_ecb_t *ecb, dtrace_actdesc_t *desc)
size = dp->dtdo_rtype.dtdt_size;
break;
- case DTRACEACT_PRINTT:
- size = dp->dtdo_rtype.dtdt_size;
- break;
-
case DTRACEACT_COMMIT: {
dtrace_action_t *act = ecb->dte_action;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h
index 8887aa8d925f..8b206a378d24 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h
@@ -369,7 +369,6 @@ typedef struct itx {
void *itx_private; /* type-specific opaque data */
itx_wr_state_t itx_wr_state; /* write state */
uint8_t itx_sync; /* synchronous transaction */
- uint64_t itx_sod; /* record size on disk */
uint64_t itx_oid; /* object id */
lr_t itx_lr; /* common part of log record */
/* followed by type-specific part of lr_xx_t and its immediate data */
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil_impl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil_impl.h
index ac908bd322ef..a1ed9e58d120 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil_impl.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil_impl.h
@@ -42,6 +42,7 @@ extern "C" {
typedef struct lwb {
zilog_t *lwb_zilog; /* back pointer to log struct */
blkptr_t lwb_blk; /* on disk address of this log blk */
+ boolean_t lwb_slog; /* lwb_blk is on SLOG device */
int lwb_nused; /* # used bytes in buffer */
int lwb_sz; /* size of block and buffer */
char *lwb_buf; /* log write buffer */
@@ -62,7 +63,6 @@ typedef struct itxs {
typedef struct itxg {
kmutex_t itxg_lock; /* lock for this structure */
uint64_t itxg_txg; /* txg for this chain */
- uint64_t itxg_sod; /* total size on disk for this txg */
itxs_t *itxg_itxs; /* sync and async itxs */
} itxg_t;
@@ -120,7 +120,6 @@ struct zilog {
kcondvar_t zl_cv_batch[2]; /* batch condition variables */
itxg_t zl_itxg[TXG_SIZE]; /* intent log txg chains */
list_t zl_itx_commit_list; /* itx list to be committed */
- uint64_t zl_itx_list_sz; /* total size of records on list */
uint64_t zl_cur_used; /* current commit log size used */
list_t zl_lwb_list; /* in-flight log write list */
kmutex_t zl_vdev_lock; /* protects zl_vdev_tree */
@@ -142,6 +141,8 @@ typedef struct zil_bp_node {
#define ZIL_MAX_LOG_DATA (SPA_OLD_MAXBLOCKSIZE - sizeof (zil_chain_t) - \
sizeof (lr_write_t))
+#define ZIL_MAX_COPIED_DATA \
+ ((SPA_OLD_MAXBLOCKSIZE - sizeof (zil_chain_t)) / 2 - sizeof (lr_write_t))
#ifdef __cplusplus
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
index da3461e10e6f..30f8d81f4c89 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
@@ -547,7 +547,7 @@ extern zio_t *zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg,
const blkptr_t *bp, uint64_t size, enum zio_flag flags);
extern int zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp,
- blkptr_t *old_bp, uint64_t size, boolean_t use_slog);
+ blkptr_t *old_bp, uint64_t size, boolean_t *slog);
extern void zio_free_zil(spa_t *spa, uint64_t txg, blkptr_t *bp);
extern void zio_flush(zio_t *zio, vdev_t *vd);
extern zio_t *zio_trim(zio_t *zio, spa_t *spa, vdev_t *vd, uint64_t offset,
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c
index 049b958605d8..31054bac5998 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c
@@ -464,20 +464,17 @@ void
zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
znode_t *zp, offset_t off, ssize_t resid, int ioflag)
{
+ uint32_t blocksize = zp->z_blksz;
itx_wr_state_t write_state;
- boolean_t slogging;
uintptr_t fsync_cnt;
- ssize_t immediate_write_sz;
if (zil_replaying(zilog, tx) || zp->z_unlinked)
return;
- immediate_write_sz = (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT)
- ? 0 : zfs_immediate_write_sz;
-
- slogging = spa_has_slogs(zilog->zl_spa) &&
- (zilog->zl_logbias == ZFS_LOGBIAS_LATENCY);
- if (resid > immediate_write_sz && !slogging && resid <= zp->z_blksz)
+ if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT)
+ write_state = WR_INDIRECT;
+ else if (!spa_has_slogs(zilog->zl_spa) &&
+ resid >= zfs_immediate_write_sz)
write_state = WR_INDIRECT;
else if (ioflag & (FSYNC | FDSYNC))
write_state = WR_COPIED;
@@ -491,30 +488,26 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
while (resid) {
itx_t *itx;
lr_write_t *lr;
- ssize_t len;
+ itx_wr_state_t wr_state = write_state;
+ ssize_t len = resid;
- /*
- * If the write would overflow the largest block then split it.
- */
- if (write_state != WR_INDIRECT && resid > ZIL_MAX_LOG_DATA)
- len = SPA_OLD_MAXBLOCKSIZE >> 1;
- else
- len = resid;
+ if (wr_state == WR_COPIED && resid > ZIL_MAX_COPIED_DATA)
+ wr_state = WR_NEED_COPY;
+ else if (wr_state == WR_INDIRECT)
+ len = MIN(blocksize - P2PHASE(off, blocksize), resid);
itx = zil_itx_create(txtype, sizeof (*lr) +
- (write_state == WR_COPIED ? len : 0));
+ (wr_state == WR_COPIED ? len : 0));
lr = (lr_write_t *)&itx->itx_lr;
- if (write_state == WR_COPIED && dmu_read(zp->z_zfsvfs->z_os,
+ if (wr_state == WR_COPIED && dmu_read(zp->z_zfsvfs->z_os,
zp->z_id, off, len, lr + 1, DMU_READ_NO_PREFETCH) != 0) {
zil_itx_destroy(itx);
itx = zil_itx_create(txtype, sizeof (*lr));
lr = (lr_write_t *)&itx->itx_lr;
- write_state = WR_NEED_COPY;
+ wr_state = WR_NEED_COPY;
}
- itx->itx_wr_state = write_state;
- if (write_state == WR_NEED_COPY)
- itx->itx_sod += len;
+ itx->itx_wr_state = wr_state;
lr->lr_foid = zp->z_id;
lr->lr_offset = off;
lr->lr_length = len;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index 17c702a335fc..d176706f777e 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -426,12 +426,8 @@ page_busy(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
continue;
}
vm_page_sbusy(pp);
- } else if (pp == NULL) {
- pp = vm_page_alloc(obj, OFF_TO_IDX(start),
- VM_ALLOC_SYSTEM | VM_ALLOC_IFCACHED |
- VM_ALLOC_SBUSY);
- } else {
- ASSERT(pp != NULL && !pp->valid);
+ } else if (pp != NULL) {
+ ASSERT(!pp->valid);
pp = NULL;
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
index 6d58078a5d9f..bef7015af835 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
@@ -88,6 +88,15 @@ SYSCTL_DECL(_vfs_zfs_trim);
SYSCTL_INT(_vfs_zfs_trim, OID_AUTO, enabled, CTLFLAG_RDTUN, &zfs_trim_enabled, 0,
"Enable ZFS TRIM");
+/*
+ * Limit SLOG write size per commit executed with synchronous priority.
+ * Any writes above that executed with lower (asynchronous) priority to
+ * limit potential SLOG device abuse by single active ZIL writer.
+ */
+uint64_t zil_slog_limit = 768 * 1024;
+SYSCTL_QUAD(_vfs_zfs, OID_AUTO, zil_slog_limit, CTLFLAG_RWTUN,
+ &zil_slog_limit, 0, "Maximal SLOG commit size with sync priority");
+
static kmem_cache_t *zil_lwb_cache;
#define LWB_EMPTY(lwb) ((BP_GET_LSIZE(&lwb->lwb_blk) - \
@@ -447,13 +456,14 @@ zil_free_log_record(zilog_t *zilog, lr_t *lrc, void *tx, uint64_t claim_txg)
}
static lwb_t *
-zil_alloc_lwb(zilog_t *zilog, blkptr_t *bp, uint64_t txg)
+zil_alloc_lwb(zilog_t *zilog, blkptr_t *bp, boolean_t slog, uint64_t txg)
{
lwb_t *lwb;
lwb = kmem_cache_alloc(zil_lwb_cache, KM_SLEEP);
lwb->lwb_zilog = zilog;
lwb->lwb_blk = *bp;
+ lwb->lwb_slog = slog;
lwb->lwb_buf = zio_buf_alloc(BP_GET_LSIZE(bp));
lwb->lwb_max_txg = txg;
lwb->lwb_zio = NULL;
@@ -516,6 +526,7 @@ zil_create(zilog_t *zilog)
dmu_tx_t *tx = NULL;
blkptr_t blk;
int error = 0;
+ boolean_t slog = FALSE;
/*
* Wait for any previous destroy to complete.
@@ -544,7 +555,7 @@ zil_create(zilog_t *zilog)
}
error = zio_alloc_zil(zilog->zl_spa, txg, &blk, NULL,
- ZIL_MIN_BLKSZ, zilog->zl_logbias == ZFS_LOGBIAS_LATENCY);
+ ZIL_MIN_BLKSZ, &slog);
if (error == 0)
zil_init_log_chain(zilog, &blk);
@@ -554,7 +565,7 @@ zil_create(zilog_t *zilog)
* Allocate a log write buffer (lwb) for the first log block.
*/
if (error == 0)
- lwb = zil_alloc_lwb(zilog, &blk, txg);
+ lwb = zil_alloc_lwb(zilog, &blk, slog, txg);
/*
* If we just allocated the first log block, commit our transaction
@@ -885,6 +896,7 @@ static void
zil_lwb_write_init(zilog_t *zilog, lwb_t *lwb)
{
zbookmark_phys_t zb;
+ zio_priority_t prio;
SET_BOOKMARK(&zb, lwb->lwb_blk.blk_cksum.zc_word[ZIL_ZC_OBJSET],
ZB_ZIL_OBJECT, ZB_ZIL_LEVEL,
@@ -895,9 +907,13 @@ zil_lwb_write_init(zilog_t *zilog, lwb_t *lwb)
ZIO_FLAG_CANFAIL);
}
if (lwb->lwb_zio == NULL) {
+ if (zilog->zl_cur_used <= zil_slog_limit || !lwb->lwb_slog)
+ prio = ZIO_PRIORITY_SYNC_WRITE;
+ else
+ prio = ZIO_PRIORITY_ASYNC_WRITE;
lwb->lwb_zio = zio_rewrite(zilog->zl_root_zio, zilog->zl_spa,
0, &lwb->lwb_blk, lwb->lwb_buf, BP_GET_LSIZE(&lwb->lwb_blk),
- zil_lwb_write_done, lwb, ZIO_PRIORITY_SYNC_WRITE,
+ zil_lwb_write_done, lwb, prio,
ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE, &zb);
}
}
@@ -917,18 +933,6 @@ uint64_t zil_block_buckets[] = {
};
/*
- * Use the slog as long as the logbias is 'latency' and the current commit size
- * is less than the limit or the total list size is less than 2X the limit.
- * Limit checking is disabled by setting zil_slog_limit to UINT64_MAX.
- */
-uint64_t zil_slog_limit = 1024 * 1024;
-SYSCTL_QUAD(_vfs_zfs, OID_AUTO, zil_slog_limit, CTLFLAG_RWTUN,
- &zil_slog_limit, 0, "Maximal commit size to use SLOG");
-#define USE_SLOG(zilog) (((zilog)->zl_logbias == ZFS_LOGBIAS_LATENCY) && \
- (((zilog)->zl_cur_used < zil_slog_limit) || \
- ((zilog)->zl_itx_list_sz < (zil_slog_limit << 1))))
-
-/*
* Start a log block write and advance to the next log block.
* Calls are serialized.
*/
@@ -943,6 +947,7 @@ zil_lwb_write_start(zilog_t *zilog, lwb_t *lwb)
uint64_t txg;
uint64_t zil_blksz, wsz;
int i, error;
+ boolean_t slog;
if (BP_GET_CHECKSUM(&lwb->lwb_blk) == ZIO_CHECKSUM_ZILOG2) {
zilc = (zil_chain_t *)lwb->lwb_buf;
@@ -999,8 +1004,7 @@ zil_lwb_write_start(zilog_t *zilog, lwb_t *lwb)
BP_ZERO(bp);
/* pass the old blkptr in order to spread log blocks across devs */
- error = zio_alloc_zil(spa, txg, bp, &lwb->lwb_blk, zil_blksz,
- USE_SLOG(zilog));
+ error = zio_alloc_zil(spa, txg, bp, &lwb->lwb_blk, zil_blksz, &slog);
if (error == 0) {
ASSERT3U(bp->blk_birth, ==, txg);
bp->blk_cksum = lwb->lwb_blk.blk_cksum;
@@ -1009,7 +1013,7 @@ zil_lwb_write_start(zilog_t *zilog, lwb_t *lwb)
/*
* Allocate a new log write buffer (lwb).
*/
- nlwb = zil_alloc_lwb(zilog, bp, txg);
+ nlwb = zil_alloc_lwb(zilog, bp, slog, txg);
/* Record the block for later vdev flushing */
zil_add_block(zilog, &lwb->lwb_blk);
@@ -1046,12 +1050,13 @@ zil_lwb_write_start(zilog_t *zilog, lwb_t *lwb)
static lwb_t *
zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb)
{
- lr_t *lrc = &itx->itx_lr; /* common log record */
- lr_write_t *lrw = (lr_write_t *)lrc;
+ lr_t *lrcb, *lrc = &itx->itx_lr; /* common log record */
+ lr_write_t *lrwb, *lrw = (lr_write_t *)lrc;
char *lr_buf;
uint64_t txg = lrc->lrc_txg;
uint64_t reclen = lrc->lrc_reclen;
uint64_t dlen = 0;
+ uint64_t dnow, lwb_sp;
if (lwb == NULL)
return (NULL);
@@ -1068,25 +1073,30 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb)
zil_lwb_write_init(zilog, lwb);
+cont:
/*
* If this record won't fit in the current log block, start a new one.
+ * For WR_NEED_COPY optimize layout for minimal number of chunks, but
+ * try to keep wasted space withing reasonable range (12%).
*/
- if (lwb->lwb_nused + reclen + dlen > lwb->lwb_sz) {
+ lwb_sp = lwb->lwb_sz - lwb->lwb_nused;
+ if (reclen > lwb_sp || (reclen + dlen > lwb_sp &&
+ lwb_sp < ZIL_MAX_LOG_DATA / 8 && (dlen % ZIL_MAX_LOG_DATA == 0 ||
+ lwb_sp < reclen + dlen % ZIL_MAX_LOG_DATA))) {
lwb = zil_lwb_write_start(zilog, lwb);
if (lwb == NULL)
return (NULL);
zil_lwb_write_init(zilog, lwb);
ASSERT(LWB_EMPTY(lwb));
- if (lwb->lwb_nused + reclen + dlen > lwb->lwb_sz) {
- txg_wait_synced(zilog->zl_dmu_pool, txg);
- return (lwb);
- }
+ lwb_sp = lwb->lwb_sz - lwb->lwb_nused;
+ ASSERT3U(reclen + MIN(dlen, sizeof(uint64_t)), <=, lwb_sp);
}
+ dnow = MIN(dlen, lwb_sp - reclen);
lr_buf = lwb->lwb_buf + lwb->lwb_nused;
bcopy(lrc, lr_buf, reclen);
- lrc = (lr_t *)lr_buf;
- lrw = (lr_write_t *)lrc;
+ lrcb = (lr_t *)lr_buf;
+ lrwb = (lr_write_t *)lrcb;
/*
* If it's a write, fetch the data or get its blkptr as appropriate.
@@ -1098,16 +1108,19 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb)
char *dbuf;
int error;
- if (dlen) {
- ASSERT(itx->itx_wr_state == WR_NEED_COPY);
+ if (itx->itx_wr_state == WR_NEED_COPY) {
dbuf = lr_buf + reclen;
- lrw->lr_common.lrc_reclen += dlen;
+ lrcb->lrc_reclen += dnow;
+ if (lrwb->lr_length > dnow)
+ lrwb->lr_length = dnow;
+ lrw->lr_offset += dnow;
+ lrw->lr_length -= dnow;
} else {
ASSERT(itx->itx_wr_state == WR_INDIRECT);
dbuf = NULL;
}
error = zilog->zl_get_data(
- itx->itx_private, lrw, dbuf, lwb->lwb_zio);
+ itx->itx_private, lrwb, dbuf, lwb->lwb_zio);
if (error == EIO) {
txg_wait_synced(zilog->zl_dmu_pool, txg);
return (lwb);
@@ -1126,12 +1139,18 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb)
* equal to the itx sequence number because not all transactions
* are synchronous, and sometimes spa_sync() gets there first.
*/
- lrc->lrc_seq = ++zilog->zl_lr_seq; /* we are single threaded */
- lwb->lwb_nused += reclen + dlen;
+ lrcb->lrc_seq = ++zilog->zl_lr_seq; /* we are single threaded */
+ lwb->lwb_nused += reclen + dnow;
lwb->lwb_max_txg = MAX(lwb->lwb_max_txg, txg);
ASSERT3U(lwb->lwb_nused, <=, lwb->lwb_sz);
ASSERT0(P2PHASE(lwb->lwb_nused, sizeof (uint64_t)));
+ dlen -= dnow;
+ if (dlen > 0) {
+ zilog->zl_cur_used += reclen;
+ goto cont;
+ }
+
return (lwb);
}
@@ -1142,15 +1161,9 @@ zil_itx_create(uint64_t txtype, size_t lrsize)
lrsize = P2ROUNDUP_TYPED(lrsize, sizeof (uint64_t), size_t);
-#ifdef __FreeBSD__
- if (offsetof(itx_t, itx_lr) + lrsize > PAGE_SIZE)
- itx = zio_buf_alloc(offsetof(itx_t, itx_lr) + lrsize);
- else
-#endif
itx = kmem_alloc(offsetof(itx_t, itx_lr) + lrsize, KM_SLEEP);
itx->itx_lr.lrc_txtype = txtype;
itx->itx_lr.lrc_reclen = lrsize;
- itx->itx_sod = lrsize; /* if write & WR_NEED_COPY will be increased */
itx->itx_lr.lrc_seq = 0; /* defensive */
itx->itx_sync = B_TRUE; /* default is synchronous */
@@ -1160,11 +1173,6 @@ zil_itx_create(uint64_t txtype, size_t lrsize)
void
zil_itx_destroy(itx_t *itx)
{
-#ifdef __FreeBSD__
- if (offsetof(itx_t, itx_lr) + itx->itx_lr.lrc_reclen > PAGE_SIZE)
- zio_buf_free(itx, offsetof(itx_t, itx_lr) + itx->itx_lr.lrc_reclen);
- else
-#endif
kmem_free(itx, offsetof(itx_t, itx_lr) + itx->itx_lr.lrc_reclen);
}
@@ -1184,7 +1192,8 @@ zil_itxg_clean(itxs_t *itxs)
list = &itxs->i_sync_list;
while ((itx = list_head(list)) != NULL) {
list_remove(list, itx);
- zil_itx_destroy(itx);
+ kmem_free(itx, offsetof(itx_t, itx_lr) +
+ itx->itx_lr.lrc_reclen);
}
cookie = NULL;
@@ -1193,7 +1202,8 @@ zil_itxg_clean(itxs_t *itxs)
list = &ian->ia_list;
while ((itx = list_head(list)) != NULL) {
list_remove(list, itx);
- zil_itx_destroy(itx);
+ kmem_free(itx, offsetof(itx_t, itx_lr) +
+ itx->itx_lr.lrc_reclen);
}
list_destroy(list);
kmem_free(ian, sizeof (itx_async_node_t));
@@ -1258,7 +1268,8 @@ zil_remove_async(zilog_t *zilog, uint64_t oid)
}
while ((itx = list_head(&clean_list)) != NULL) {
list_remove(&clean_list, itx);
- zil_itx_destroy(itx);
+ kmem_free(itx, offsetof(itx_t, itx_lr) +
+ itx->itx_lr.lrc_reclen);
}
list_destroy(&clean_list);
}
@@ -1301,11 +1312,8 @@ zil_itx_assign(zilog_t *zilog, itx_t *itx, dmu_tx_t *tx)
* this itxg. Save the itxs for release below.
* This should be rare.
*/
- atomic_add_64(&zilog->zl_itx_list_sz, -itxg->itxg_sod);
- itxg->itxg_sod = 0;
clean = itxg->itxg_itxs;
}
- ASSERT(itxg->itxg_sod == 0);
itxg->itxg_txg = txg;
itxs = itxg->itxg_itxs = kmem_zalloc(sizeof (itxs_t), KM_SLEEP);
@@ -1317,8 +1325,6 @@ zil_itx_assign(zilog_t *zilog, itx_t *itx, dmu_tx_t *tx)
}
if (itx->itx_sync) {
list_insert_tail(&itxs->i_sync_list, itx);
- atomic_add_64(&zilog->zl_itx_list_sz, itx->itx_sod);
- itxg->itxg_sod += itx->itx_sod;
} else {
avl_tree_t *t = &itxs->i_async_tree;
uint64_t foid = ((lr_ooo_t *)&itx->itx_lr)->lr_foid;
@@ -1366,8 +1372,6 @@ zil_clean(zilog_t *zilog, uint64_t synced_txg)
ASSERT3U(itxg->itxg_txg, <=, synced_txg);
ASSERT(itxg->itxg_txg != 0);
ASSERT(zilog->zl_clean_taskq != NULL);
- atomic_add_64(&zilog->zl_itx_list_sz, -itxg->itxg_sod);
- itxg->itxg_sod = 0;
clean_me = itxg->itxg_itxs;
itxg->itxg_itxs = NULL;
itxg->itxg_txg = 0;
@@ -1391,7 +1395,6 @@ zil_get_commit_list(zilog_t *zilog)
{
uint64_t otxg, txg;
list_t *commit_list = &zilog->zl_itx_commit_list;
- uint64_t push_sod = 0;
if (spa_freeze_txg(zilog->zl_spa) != UINT64_MAX) /* ziltest support */
otxg = ZILTEST_TXG;
@@ -1408,12 +1411,9 @@ zil_get_commit_list(zilog_t *zilog)
}
list_move_tail(commit_list, &itxg->itxg_itxs->i_sync_list);
- push_sod += itxg->itxg_sod;
- itxg->itxg_sod = 0;
mutex_exit(&itxg->itxg_lock);
}
- atomic_add_64(&zilog->zl_itx_list_sz, -push_sod);
}
/*
@@ -1508,7 +1508,8 @@ zil_commit_writer(zilog_t *zilog)
if (txg > spa_last_synced_txg(spa) || txg > spa_freeze_txg(spa))
lwb = zil_lwb_commit(zilog, itx, lwb);
list_remove(&zilog->zl_itx_commit_list, itx);
- zil_itx_destroy(itx);
+ kmem_free(itx, offsetof(itx_t, itx_lr)
+ + itx->itx_lr.lrc_reclen);
}
DTRACE_PROBE1(zil__cw2, zilog_t *, zilog);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
index 7cf8dc46a3af..0b6813a96a9a 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
@@ -2908,20 +2908,21 @@ zio_dva_unallocate(zio_t *zio, zio_gang_node_t *gn, blkptr_t *bp)
*/
int
zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, blkptr_t *old_bp,
- uint64_t size, boolean_t use_slog)
+ uint64_t size, boolean_t *slog)
{
int error = 1;
ASSERT(txg > spa_syncing_txg(spa));
- if (use_slog) {
- error = metaslab_alloc(spa, spa_log_class(spa), size,
- new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID, NULL);
- }
-
- if (error) {
+ error = metaslab_alloc(spa, spa_log_class(spa), size,
+ new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID, NULL);
+ if (error == 0) {
+ *slog = TRUE;
+ } else {
error = metaslab_alloc(spa, spa_normal_class(spa), size,
new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID, NULL);
+ if (error == 0)
+ *slog = FALSE;
}
if (error == 0) {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
index 908de12a46ce..1847ad549069 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
@@ -1387,54 +1387,44 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, offset_t off, ssize_t resid,
{
uint32_t blocksize = zv->zv_volblocksize;
zilog_t *zilog = zv->zv_zilog;
- boolean_t slogging;
- ssize_t immediate_write_sz;
+ itx_wr_state_t write_state;
if (zil_replaying(zilog, tx))
return;
- immediate_write_sz = (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT)
- ? 0 : zvol_immediate_write_sz;
-
- slogging = spa_has_slogs(zilog->zl_spa) &&
- (zilog->zl_logbias == ZFS_LOGBIAS_LATENCY);
+ if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT)
+ write_state = WR_INDIRECT;
+ else if (!spa_has_slogs(zilog->zl_spa) &&
+ resid >= blocksize && blocksize > zvol_immediate_write_sz)
+ write_state = WR_INDIRECT;
+ else if (sync)
+ write_state = WR_COPIED;
+ else
+ write_state = WR_NEED_COPY;
while (resid) {
itx_t *itx;
lr_write_t *lr;
- ssize_t len;
- itx_wr_state_t write_state;
+ itx_wr_state_t wr_state = write_state;
+ ssize_t len = resid;
- /*
- * Unlike zfs_log_write() we can be called with
- * upto DMU_MAX_ACCESS/2 (5MB) writes.
- */
- if (blocksize > immediate_write_sz && !slogging &&
- resid >= blocksize && off % blocksize == 0) {
- write_state = WR_INDIRECT; /* uses dmu_sync */
- len = blocksize;
- } else if (sync) {
- write_state = WR_COPIED;
- len = MIN(ZIL_MAX_LOG_DATA, resid);
- } else {
- write_state = WR_NEED_COPY;
- len = MIN(ZIL_MAX_LOG_DATA, resid);
- }
+ if (wr_state == WR_COPIED && resid > ZIL_MAX_COPIED_DATA)
+ wr_state = WR_NEED_COPY;
+ else if (wr_state == WR_INDIRECT)
+ len = MIN(blocksize - P2PHASE(off, blocksize), resid);
itx = zil_itx_create(TX_WRITE, sizeof (*lr) +
- (write_state == WR_COPIED ? len : 0));
+ (wr_state == WR_COPIED ? len : 0));
lr = (lr_write_t *)&itx->itx_lr;
- if (write_state == WR_COPIED && dmu_read(zv->zv_objset,
+ if (wr_state == WR_COPIED && dmu_read(zv->zv_objset,
ZVOL_OBJ, off, len, lr + 1, DMU_READ_NO_PREFETCH) != 0) {
zil_itx_destroy(itx);
itx = zil_itx_create(TX_WRITE, sizeof (*lr));
lr = (lr_write_t *)&itx->itx_lr;
- write_state = WR_NEED_COPY;
+ wr_state = WR_NEED_COPY;
}
- itx->itx_wr_state = write_state;
- if (write_state == WR_NEED_COPY)
- itx->itx_sod += len;
+ itx->itx_wr_state = wr_state;
lr->lr_foid = ZVOL_OBJ;
lr->lr_offset = off;
lr->lr_length = len;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
index 92d35690ad75..f489bb0629d9 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
@@ -308,7 +308,7 @@ typedef enum dtrace_probespec {
#define DIF_SUBR_TOUPPER 44
#define DIF_SUBR_TOLOWER 45
#define DIF_SUBR_MEMREF 46
-#define DIF_SUBR_TYPEREF 47
+#define DIF_SUBR_UNUSED 47
#define DIF_SUBR_SX_SHARED_HELD 48
#define DIF_SUBR_SX_EXCLUSIVE_HELD 49
#define DIF_SUBR_SX_ISEXCLUSIVE 50
@@ -429,7 +429,6 @@ typedef struct dtrace_difv {
#define DTRACEACT_TRACEMEM 6 /* tracemem() action */
#define DTRACEACT_TRACEMEM_DYNSIZE 7 /* dynamic tracemem() size */
#define DTRACEACT_PRINTM 8 /* printm() action (BSD) */
-#define DTRACEACT_PRINTT 9 /* printt() action (BSD) */
#define DTRACEACT_PROC 0x0100
#define DTRACEACT_USTACK (DTRACEACT_PROC + 1)
diff --git a/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c b/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c
index e1f95de8a8d8..1ffe6a7a809d 100644
--- a/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c
+++ b/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c
@@ -1871,9 +1871,7 @@ fasttrap_getreg(struct reg *rp, uint_t reg)
case REG_ERR: return (rp->r_err);
case REG_RIP: return (rp->r_rip);
case REG_CS: return (rp->r_cs);
-#ifdef illumos
- case REG_RFL: return (rp->r_rfl);
-#endif
+ case REG_RFL: return (rp->r_rflags);
case REG_RSP: return (rp->r_rsp);
case REG_SS: return (rp->r_ss);
case REG_FS: return (rp->r_fs);
diff --git a/sys/conf/Makefile.mips b/sys/conf/Makefile.mips
index d1e692390803..de006c018e6d 100644
--- a/sys/conf/Makefile.mips
+++ b/sys/conf/Makefile.mips
@@ -52,6 +52,8 @@ CFLAGS+=${EXTRA_FLAGS} $(ARCH_FLAGS)
HACK_EXTRA_FLAGS+=${EXTRA_FLAGS} $(ARCH_FLAGS)
TRAMP_ARCH_FLAGS?=$(ARCH_FLAGS)
TRAMP_EXTRA_FLAGS=${EXTRA_FLAGS} ${TRAMP_ARCH_FLAGS}
+# Kernel code is always compiled with soft-float on MIPS
+TRAMP_EXTRA_FLAGS+=-msoft-float
.if ${MACHINE_ARCH:Mmips64*} != ""
TRAMP_ELFSIZE=64
.else
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index f964d256a61b..ebb7d4245454 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1903,6 +1903,7 @@ device amphy # AMD AM79c873 / Davicom DM910{1,2}
device atphy # Attansic/Atheros F1
device axphy # Asix Semiconductor AX88x9x
device bmtphy # Broadcom BCM5201/BCM5202 and 3Com 3c905C
+device bnxt # Broadcom NetXtreme-C/NetXtreme-E
device brgphy # Broadcom BCM54xx/57xx 1000baseTX
device ciphy # Cicada/Vitesse CS/VSC8xxx
device e1000phy # Marvell 88E1000 1000/100/10-BT
@@ -1943,6 +1944,7 @@ device xmphy # XaQti XMAC II
# BCM570x family of controllers, including the 3Com 3c996-T,
# the Netgear GA302T, the SysKonnect SK-9D21 and SK-9D41, and
# the embedded gigE NICs on Dell PowerEdge 2550 servers.
+# bnxt: Broadcom NetXtreme-C and NetXtreme-E PCIe 10/25/50G Ethernet adapters.
# bxe: Broadcom NetXtreme II (BCM5771X/BCM578XX) PCIe 10Gb Ethernet
# adapters.
# bwi: Broadcom BCM430* and BCM431* family of wireless adapters.
diff --git a/sys/conf/files b/sys/conf/files
index 7a92df184c73..07bbfb8c41c6 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1242,6 +1242,10 @@ dev/bktr/bktr_i2c.c optional bktr pci smbus
dev/bktr/bktr_os.c optional bktr pci
dev/bktr/bktr_tuner.c optional bktr pci
dev/bktr/msp34xx.c optional bktr pci
+dev/bnxt/bnxt_hwrm.c optional bnxt iflib pci
+dev/bnxt/bnxt_sysctl.c optional bnxt iflib pci
+dev/bnxt/bnxt_txrx.c optional bnxt iflib pci
+dev/bnxt/if_bnxt.c optional bnxt iflib pci
dev/buslogic/bt.c optional bt
dev/buslogic/bt_eisa.c optional bt eisa
dev/buslogic/bt_isa.c optional bt isa
@@ -1398,6 +1402,7 @@ dev/dcons/dcons.c optional dcons
dev/dcons/dcons_crom.c optional dcons_crom
dev/dcons/dcons_os.c optional dcons
dev/de/if_de.c optional de pci
+dev/dme/if_dme.c optional dme
dev/dpt/dpt_eisa.c optional dpt eisa
dev/dpt/dpt_pci.c optional dpt pci
dev/dpt/dpt_scsi.c optional dpt
@@ -1466,6 +1471,49 @@ dev/drm/via_map.c optional viadrm
dev/drm/via_mm.c optional viadrm
dev/drm/via_verifier.c optional viadrm
dev/drm/via_video.c optional viadrm
+dev/drm2/drm_agpsupport.c optional drm2
+dev/drm2/drm_auth.c optional drm2
+dev/drm2/drm_bufs.c optional drm2
+dev/drm2/drm_buffer.c optional drm2
+dev/drm2/drm_context.c optional drm2
+dev/drm2/drm_crtc.c optional drm2
+dev/drm2/drm_crtc_helper.c optional drm2
+dev/drm2/drm_dma.c optional drm2
+dev/drm2/drm_dp_helper.c optional drm2
+dev/drm2/drm_dp_iic_helper.c optional drm2
+dev/drm2/drm_drv.c optional drm2
+dev/drm2/drm_edid.c optional drm2
+dev/drm2/drm_fb_helper.c optional drm2
+dev/drm2/drm_fops.c optional drm2
+dev/drm2/drm_gem.c optional drm2
+dev/drm2/drm_gem_names.c optional drm2
+dev/drm2/drm_global.c optional drm2
+dev/drm2/drm_hashtab.c optional drm2
+dev/drm2/drm_ioctl.c optional drm2
+dev/drm2/drm_irq.c optional drm2
+dev/drm2/drm_linux_list_sort.c optional drm2
+dev/drm2/drm_lock.c optional drm2
+dev/drm2/drm_memory.c optional drm2
+dev/drm2/drm_mm.c optional drm2
+dev/drm2/drm_modes.c optional drm2
+dev/drm2/drm_pci.c optional drm2
+dev/drm2/drm_scatter.c optional drm2
+dev/drm2/drm_stub.c optional drm2
+dev/drm2/drm_sysctl.c optional drm2
+dev/drm2/drm_vm.c optional drm2
+dev/drm2/drm_os_freebsd.c optional drm2
+dev/drm2/ttm/ttm_agp_backend.c optional drm2
+dev/drm2/ttm/ttm_lock.c optional drm2
+dev/drm2/ttm/ttm_object.c optional drm2
+dev/drm2/ttm/ttm_tt.c optional drm2
+dev/drm2/ttm/ttm_bo_util.c optional drm2
+dev/drm2/ttm/ttm_bo.c optional drm2
+dev/drm2/ttm/ttm_bo_manager.c optional drm2
+dev/drm2/ttm/ttm_execbuf_util.c optional drm2
+dev/drm2/ttm/ttm_memory.c optional drm2
+dev/drm2/ttm/ttm_page_alloc.c optional drm2
+dev/drm2/ttm/ttm_bo_vm.c optional drm2
+dev/drm2/ati_pcigart.c optional drm2 agp pci
dev/ed/if_ed.c optional ed
dev/ed/if_ed_novell.c optional ed
dev/ed/if_ed_rtl80x9.c optional ed
@@ -1614,6 +1662,7 @@ dev/gpio/gpioc.c optional gpio \
dev/gpio/gpioiic.c optional gpioiic
dev/gpio/gpioled.c optional gpioled !fdt
dev/gpio/gpioled_fdt.c optional gpioled fdt
+dev/gpio/gpiopower.c optional gpiopower fdt
dev/gpio/gpioregulator.c optional gpioregulator fdt ext_resources
dev/gpio/gpiospi.c optional gpiospi
dev/gpio/gpio_if.m optional gpio
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 99d4aef326b1..c6609a31fbf4 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -292,18 +292,20 @@ dev/hwpmc/hwpmc_uncore.c optional hwpmc
dev/hwpmc/hwpmc_piv.c optional hwpmc
dev/hwpmc/hwpmc_tsc.c optional hwpmc
dev/hwpmc/hwpmc_x86.c optional hwpmc
+dev/hyperv/pcib/vmbus_pcib.c optional hyperv pci
dev/hyperv/netvsc/hn_nvs.c optional hyperv
dev/hyperv/netvsc/hn_rndis.c optional hyperv
dev/hyperv/netvsc/if_hn.c optional hyperv
dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv
dev/hyperv/utilities/hv_heartbeat.c optional hyperv
dev/hyperv/utilities/hv_kvp.c optional hyperv
+dev/hyperv/utilities/hv_snapshot.c optional hyperv
dev/hyperv/utilities/hv_shutdown.c optional hyperv
dev/hyperv/utilities/hv_timesync.c optional hyperv
dev/hyperv/utilities/hv_util.c optional hyperv
dev/hyperv/vmbus/hyperv.c optional hyperv
dev/hyperv/vmbus/hyperv_busdma.c optional hyperv
-dev/hyperv/vmbus/vmbus.c optional hyperv
+dev/hyperv/vmbus/vmbus.c optional hyperv pci
dev/hyperv/vmbus/vmbus_br.c optional hyperv
dev/hyperv/vmbus/vmbus_chan.c optional hyperv
dev/hyperv/vmbus/vmbus_et.c optional hyperv
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index ea7b7d4b4431..879515185c71 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -52,7 +52,6 @@ arm/arm/pmu.c standard
arm/broadcom/bcm2835/bcm2835_audio.c optional sound vchiq \
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
arm/broadcom/bcm2835/bcm2835_bsc.c optional bcm2835_bsc soc_brcm_bcm2837
-arm/broadcom/bcm2835/bcm2835_common.c optional fdt soc_brcm_bcm2837
arm/broadcom/bcm2835/bcm2835_cpufreq.c optional soc_brcm_bcm2837
arm/broadcom/bcm2835/bcm2835_dma.c optional soc_brcm_bcm2837
arm/broadcom/bcm2835/bcm2835_fbd.c optional vt soc_brcm_bcm2837
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 681b81f218be..597376de1a23 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -249,18 +249,20 @@ dev/hwpmc/hwpmc_piv.c optional hwpmc
dev/hwpmc/hwpmc_ppro.c optional hwpmc
dev/hwpmc/hwpmc_tsc.c optional hwpmc
dev/hwpmc/hwpmc_x86.c optional hwpmc
+dev/hyperv/pcib/vmbus_pcib.c optional hyperv pci
dev/hyperv/netvsc/hn_nvs.c optional hyperv
dev/hyperv/netvsc/hn_rndis.c optional hyperv
dev/hyperv/netvsc/if_hn.c optional hyperv
dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv
dev/hyperv/utilities/hv_heartbeat.c optional hyperv
dev/hyperv/utilities/hv_kvp.c optional hyperv
+dev/hyperv/utilities/hv_snapshot.c optional hyperv
dev/hyperv/utilities/hv_shutdown.c optional hyperv
dev/hyperv/utilities/hv_timesync.c optional hyperv
dev/hyperv/utilities/hv_util.c optional hyperv
dev/hyperv/vmbus/hyperv.c optional hyperv
dev/hyperv/vmbus/hyperv_busdma.c optional hyperv
-dev/hyperv/vmbus/vmbus.c optional hyperv
+dev/hyperv/vmbus/vmbus.c optional hyperv pci
dev/hyperv/vmbus/vmbus_br.c optional hyperv
dev/hyperv/vmbus/vmbus_chan.c optional hyperv
dev/hyperv/vmbus/vmbus_et.c optional hyperv
diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
index 0a2d9a65ee76..ee72dbe0ebe1 100644
--- a/sys/conf/kern.pre.mk
+++ b/sys/conf/kern.pre.mk
@@ -74,7 +74,7 @@ CFLAGS+= ${INCLUDES} -D_KERNEL -DHAVE_KERNEL_OPTION_HEADERS -include opt_global.
CFLAGS_PARAM_INLINE_UNIT_GROWTH?=100
CFLAGS_PARAM_LARGE_FUNCTION_GROWTH?=1000
.if ${MACHINE_CPUARCH} == "mips"
-CFLAGS_ARCH_PARAMS?=--param max-inline-insns-single=1000
+CFLAGS_ARCH_PARAMS?=--param max-inline-insns-single=1000 -DMACHINE_ARCH='"${MACHINE_ARCH}"'
.endif
CFLAGS.gcc+= -fno-common -fms-extensions -finline-limit=${INLINE_LIMIT}
CFLAGS.gcc+= --param inline-unit-growth=${CFLAGS_PARAM_INLINE_UNIT_GROWTH}
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index ca2ebc82247b..72e9ae60610a 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -39,6 +39,28 @@ fi
RELEASE="${REVISION}-${BRANCH}"
VERSION="${TYPE} ${RELEASE}"
+#
+# findvcs dir
+# Looks up directory dir at world root and up the filesystem
+#
+findvcs()
+{
+ local savedir
+
+ savedir=$(pwd)
+ cd ${SYSDIR}/..
+ while [ $(pwd) != "/" ]; do
+ if [ -d "./$1" ]; then
+ VCSDIR=$(pwd)"/$1"
+ cd ${savedir}
+ return 0
+ fi
+ cd ..
+ done
+ cd ${savedir}
+ return 1
+}
+
if [ -z "${SYSDIR}" ]; then
SYSDIR=$(dirname $0)/..
fi
@@ -142,19 +164,20 @@ for dir in /usr/bin /usr/local/bin; do
p4_cmd=${dir}/p4
fi
done
-if [ -d "${SYSDIR}/../.git" ] ; then
+
+if findvcs .git; then
for dir in /usr/bin /usr/local/bin; do
if [ -x "${dir}/git" ] ; then
- git_cmd="${dir}/git --git-dir=${SYSDIR}/../.git"
+ git_cmd="${dir}/git --git-dir=${VCSDIR}"
break
fi
done
fi
-if [ -d "${SYSDIR}/../.hg" ] ; then
+if findvcs .hg; then
for dir in /usr/bin /usr/local/bin; do
if [ -x "${dir}/hg" ] ; then
- hg_cmd="${dir}/hg -R ${SYSDIR}/.."
+ hg_cmd="${dir}/hg -R ${VCSDIR}"
break
fi
done
@@ -193,7 +216,7 @@ if [ -n "$git_cmd" ] ; then
if [ -n "$git_b" ] ; then
git="${git}(${git_b})"
fi
- if $git_cmd --work-tree=${SYSDIR}/.. diff-index \
+ if $git_cmd --work-tree=${VCSDIR}/.. diff-index \
--name-only HEAD | read dummy; then
git="${git}-dirty"
fi
diff --git a/sys/conf/options b/sys/conf/options
index 79f71a8e487c..da04567fa48d 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -220,6 +220,7 @@ SYSVSHM opt_sysvipc.h
SW_WATCHDOG opt_watchdog.h
TURNSTILE_PROFILING
UMTX_PROFILING
+UMTX_CHAINS opt_global.h
VERBOSE_SYSINIT
# POSIX kernel options
@@ -992,7 +993,11 @@ BHND_LOGLEVEL opt_global.h
# GPIO and child devices
GPIO_SPI_DEBUG opt_gpio.h
+# etherswitch(4) driver
+RTL8366_SOFT_RESET opt_etherswitch.h
+
# evdev protocol support
EVDEV_SUPPORT opt_evdev.h
EVDEV_DEBUG opt_evdev.h
UINPUT_DEBUG opt_evdev.h
+
diff --git a/sys/conf/options.riscv b/sys/conf/options.riscv
index c263bd860875..af6a89e80f19 100644
--- a/sys/conf/options.riscv
+++ b/sys/conf/options.riscv
@@ -1,4 +1,4 @@
# $FreeBSD$
RISCV opt_global.h
-VFP opt_global.h
+FPE opt_global.h
diff --git a/sys/contrib/ncsw/inc/xx_ext.h b/sys/contrib/ncsw/inc/xx_ext.h
index ce8cae310059..f011b58b65a2 100644
--- a/sys/contrib/ncsw/inc/xx_ext.h
+++ b/sys/contrib/ncsw/inc/xx_ext.h
@@ -930,9 +930,4 @@ t_Error XX_IpcSendMessage(t_Handle h_Session,
/** @} */ /* end of xx_ipc group */
/** @} */ /* end of xx_id group */
-/** FreeBSD Specific additions. */
-void XX_TrackInit(void);
-physAddress_t XX_TrackAddress(void *addr);
-void XX_UntrackAddress(void *addr);
-
#endif /* __XX_EXT_H */
diff --git a/sys/contrib/ncsw/user/env/xx.c b/sys/contrib/ncsw/user/env/xx.c
index 621c2025e16c..c153c69dcef2 100644
--- a/sys/contrib/ncsw/user/env/xx.c
+++ b/sys/contrib/ncsw/user/env/xx.c
@@ -51,6 +51,7 @@
#include <dev/dpaa/qman.h>
#include <dev/dpaa/portals.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
#include "error_ext.h"
#include "std_ext.h"
#include "list_ext.h"
@@ -124,19 +125,6 @@ struct XX_PortalInfo {
static struct XX_PortalInfo XX_PInfo;
-/* The lower 9 bits, through emprical testing, tend to be 0. */
-#define XX_MALLOC_TRACK_SHIFT 9
-
-typedef struct XX_MallocTrackStruct {
- LIST_ENTRY(XX_MallocTrackStruct) entries;
- physAddress_t pa;
- void *va;
-} XX_MallocTrackStruct;
-
-LIST_HEAD(XX_MallocTrackerList, XX_MallocTrackStruct) *XX_MallocTracker;
-u_long XX_MallocHashMask;
-static XX_MallocTrackStruct * XX_FindTracker(physAddress_t pa);
-
void
XX_Exit(int status)
{
@@ -266,7 +254,6 @@ XX_FreeSmart(void *p)
KASSERT(XX_MallocSmartMap[start] > 0,
("XX_FreeSmart: Double or mid-block free!\n"));
- XX_UntrackAddress(p);
/* Free region */
slices = XX_MallocSmartMap[start];
XX_MallocSmartMapClear(start, slices);
@@ -279,8 +266,6 @@ void
XX_Free(void *p)
{
- if (p != NULL)
- XX_UntrackAddress(p);
free(p, M_NETCOMMSW);
}
@@ -758,6 +743,11 @@ XX_VirtToPhys(void *addr)
if (addr == NULL)
return (-1);
+ /* Check CCSR */
+ if ((vm_offset_t)addr >= ccsrbar_va &&
+ (vm_offset_t)addr < ccsrbar_va + ccsrbar_size)
+ return (((vm_offset_t)addr - ccsrbar_va) + ccsrbar_pa);
+
/* Handle BMAN mappings */
if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[BM_PORTAL]) &&
((vm_offset_t)addr < XX_PInfo.portal_ce_va[BM_PORTAL] +
@@ -784,10 +774,12 @@ XX_VirtToPhys(void *addr)
return (XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] +
(vm_offset_t)addr - XX_PInfo.portal_ci_va[QM_PORTAL]);
- paddr = XX_TrackAddress(addr);
- if (paddr == -1)
+ paddr = pmap_kextract((vm_offset_t)addr);
+ if (paddr == 0)
printf("NetCommSW: "
"Unable to translate virtual address 0x%08X!\n", addr);
+ else
+ pmap_track_page(kernel_pmap, (vm_offset_t)addr);
return (paddr);
}
@@ -795,9 +787,15 @@ XX_VirtToPhys(void *addr)
void *
XX_PhysToVirt(physAddress_t addr)
{
- XX_MallocTrackStruct *ts;
+ struct pv_entry *pv;
+ vm_page_t page;
int cpu;
+ /* Check CCSR */
+ if (addr >= ccsrbar_pa && addr < ccsrbar_pa + ccsrbar_size)
+ return ((void *)((vm_offset_t)(addr - ccsrbar_pa) +
+ ccsrbar_va));
+
cpu = PCPU_GET(cpuid);
/* Handle BMAN mappings */
@@ -826,12 +824,11 @@ XX_PhysToVirt(physAddress_t addr)
return ((void *)(XX_PInfo.portal_ci_va[QM_PORTAL] +
(vm_offset_t)(addr - XX_PInfo.portal_ci_pa[QM_PORTAL][cpu])));
- mtx_lock(&XX_MallocTrackLock);
- ts = XX_FindTracker(addr);
- mtx_unlock(&XX_MallocTrackLock);
+ page = PHYS_TO_VM_PAGE(addr);
+ pv = TAILQ_FIRST(&page->md.pv_list);
- if (ts != NULL)
- return ts->va;
+ if (pv != NULL)
+ return ((void *)(pv->pv_va + ((vm_offset_t)addr & PAGE_MASK)));
printf("NetCommSW: "
"Unable to translate physical address 0x%08llX!\n", addr);
@@ -877,72 +874,3 @@ XX_PortalSetInfo(device_t dev)
end:
free(dev_name, M_TEMP);
}
-
-static inline XX_MallocTrackStruct *
-XX_FindTracker(physAddress_t pa)
-{
- struct XX_MallocTrackerList *l;
- XX_MallocTrackStruct *tp;
-
- l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask];
-
- LIST_FOREACH(tp, l, entries) {
- if (tp->pa == pa)
- return tp;
- }
-
- return NULL;
-}
-
-void
-XX_TrackInit(void)
-{
- if (XX_MallocTracker == NULL) {
- XX_MallocTracker = hashinit(64, M_NETCOMMSW_MT,
- &XX_MallocHashMask);
- }
-}
-
-physAddress_t
-XX_TrackAddress(void *addr)
-{
- physAddress_t pa;
- struct XX_MallocTrackerList *l;
- XX_MallocTrackStruct *ts;
-
- pa = pmap_kextract((vm_offset_t)addr);
-
- l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask];
-
- mtx_lock(&XX_MallocTrackLock);
- if (XX_FindTracker(pa) == NULL) {
- ts = malloc(sizeof(*ts), M_NETCOMMSW_MT, M_NOWAIT);
- if (ts == NULL)
- return (-1);
- ts->va = addr;
- ts->pa = pa;
- LIST_INSERT_HEAD(l, ts, entries);
- }
- mtx_unlock(&XX_MallocTrackLock);
-
- return (pa);
-}
-
-void
-XX_UntrackAddress(void *addr)
-{
- physAddress_t pa;
- XX_MallocTrackStruct *ts;
-
- pa = pmap_kextract((vm_offset_t)addr);
-
- KASSERT(XX_MallocTracker != NULL,
- ("Untracking an address before it's even initialized!\n"));
-
- mtx_lock(&XX_MallocTrackLock);
- ts = XX_FindTracker(pa);
- if (ts != NULL)
- LIST_REMOVE(ts, entries);
- mtx_unlock(&XX_MallocTrackLock);
- free(ts, M_NETCOMMSW_MT);
-}
diff --git a/sys/contrib/vchiq/interface/compat/vchi_bsd.c b/sys/contrib/vchiq/interface/compat/vchi_bsd.c
index 3d939b130a22..5e9965f03c73 100644
--- a/sys/contrib/vchiq/interface/compat/vchi_bsd.c
+++ b/sys/contrib/vchiq/interface/compat/vchi_bsd.c
@@ -300,7 +300,6 @@ void sema_sysinit(void *arg)
{
struct semaphore *s = arg;
- printf("sema_sysinit\n");
_sema_init(s, 1);
}
diff --git a/sys/dev/acpi_support/acpi_hp.c b/sys/dev/acpi_support/acpi_hp.c
index ec8589659438..e9de245e264a 100644
--- a/sys/dev/acpi_support/acpi_hp.c
+++ b/sys/dev/acpi_support/acpi_hp.c
@@ -66,11 +66,17 @@ ACPI_MODULE_NAME("HP")
#define ACPI_HP_WMI_BIOS_GUID "5FB7F034-2C63-45E9-BE91-3D44E2C707E4"
#define ACPI_HP_WMI_CMI_GUID "2D114B49-2DFB-4130-B8FE-4A3C09E75133"
-#define ACPI_HP_WMI_DISPLAY_COMMAND 0x1
-#define ACPI_HP_WMI_HDDTEMP_COMMAND 0x2
-#define ACPI_HP_WMI_ALS_COMMAND 0x3
-#define ACPI_HP_WMI_DOCK_COMMAND 0x4
-#define ACPI_HP_WMI_WIRELESS_COMMAND 0x5
+#define ACPI_HP_WMI_DISPLAY_COMMAND 0x1
+#define ACPI_HP_WMI_HDDTEMP_COMMAND 0x2
+#define ACPI_HP_WMI_ALS_COMMAND 0x3
+#define ACPI_HP_WMI_DOCK_COMMAND 0x4
+#define ACPI_HP_WMI_WIRELESS_COMMAND 0x5
+#define ACPI_HP_WMI_BIOS_COMMAND 0x9
+#define ACPI_HP_WMI_FEATURE_COMMAND 0xb
+#define ACPI_HP_WMI_HOTKEY_COMMAND 0xc
+#define ACPI_HP_WMI_FEATURE2_COMMAND 0xd
+#define ACPI_HP_WMI_WIRELESS2_COMMAND 0x1b
+#define ACPI_HP_WMI_POSTCODEERROR_COMMAND 0x2a
#define ACPI_HP_METHOD_WLAN_ENABLED 1
#define ACPI_HP_METHOD_WLAN_RADIO 2
@@ -104,11 +110,32 @@ ACPI_MODULE_NAME("HP")
#define HP_MASK_BLUETOOTH_ENABLED 0x20000
#define HP_MASK_WLAN_ENABLED 0x200
+#define ACPI_HP_EVENT_DOCK 0x01
+#define ACPI_HP_EVENT_PARK_HDD 0x02
+#define ACPI_HP_EVENT_SMART_ADAPTER 0x03
+#define ACPI_HP_EVENT_BEZEL_BUTTON 0x04
+#define ACPI_HP_EVENT_WIRELESS 0x05
+#define ACPI_HP_EVENT_CPU_BATTERY_THROTTLE 0x06
+#define ACPI_HP_EVENT_LOCK_SWITCH 0x07
+#define ACPI_HP_EVENT_LID_SWITCH 0x08
+#define ACPI_HP_EVENT_SCREEN_ROTATION 0x09
+#define ACPI_HP_EVENT_COOLSENSE_SYSTEM_MOBILE 0x0A
+#define ACPI_HP_EVENT_COOLSENSE_SYSTEM_HOT 0x0B
+#define ACPI_HP_EVENT_PROXIMITY_SENSOR 0x0C
+#define ACPI_HP_EVENT_BACKLIT_KB_BRIGHTNESS 0x0D
+#define ACPI_HP_EVENT_PEAKSHIFT_PERIOD 0x0F
+#define ACPI_HP_EVENT_BATTERY_CHARGE_PERIOD 0x10
+
#define ACPI_HP_CMI_DETAIL_PATHS 0x01
#define ACPI_HP_CMI_DETAIL_ENUMS 0x02
#define ACPI_HP_CMI_DETAIL_FLAGS 0x04
#define ACPI_HP_CMI_DETAIL_SHOW_MAX_INSTANCE 0x08
+#define ACPI_HP_WMI_RET_WRONG_SIGNATURE 0x02
+#define ACPI_HP_WMI_RET_UNKNOWN_COMMAND 0x03
+#define ACPI_HP_WMI_RET_UNKNOWN_CMDTYPE 0x04
+#define ACPI_HP_WMI_RET_INVALID_PARAMETERS 0x05
+
struct acpi_hp_inst_seq_pair {
UINT32 sequence; /* sequence number as suggested by cmi bios */
UINT8 instance; /* object instance on guid */
@@ -119,6 +146,7 @@ struct acpi_hp_softc {
device_t wmi_dev;
int has_notify; /* notification GUID found */
int has_cmi; /* CMI GUID found */
+ int has_wireless; /* Wireless command found */
int cmi_detail; /* CMI detail level
(set by sysctl) */
int verbose; /* add debug output */
@@ -287,7 +315,7 @@ static int acpi_hp_sysctl_set(struct acpi_hp_softc *sc, int method,
int arg, int oldarg);
static int acpi_hp_sysctl_get(struct acpi_hp_softc *sc, int method);
static int acpi_hp_exec_wmi_command(device_t wmi_dev, int command,
- int is_write, int val);
+ int is_write, int val, int *retval);
static void acpi_hp_notify(ACPI_HANDLE h, UINT32 notify, void *context);
static int acpi_hp_get_cmi_block(device_t wmi_dev, const char* guid,
UINT8 instance, char* outbuf, size_t outsize,
@@ -332,13 +360,18 @@ MODULE_DEPEND(acpi_hp, acpi, 1, 1, 1);
static void
acpi_hp_evaluate_auto_on_off(struct acpi_hp_softc *sc)
{
+ int res;
int wireless;
int new_wlan_status;
int new_bluetooth_status;
int new_wwan_status;
- wireless = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0);
+ res = acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &wireless);
+ if (res != 0) {
+ device_printf(sc->wmi_dev, "Wireless command error %x\n", res);
+ return;
+ }
new_wlan_status = -1;
new_bluetooth_status = -1;
new_wwan_status = -1;
@@ -348,41 +381,41 @@ acpi_hp_evaluate_auto_on_off(struct acpi_hp_softc *sc)
if (sc->wlan_disable_if_radio_off && !(wireless & HP_MASK_WLAN_RADIO)
&& (wireless & HP_MASK_WLAN_ENABLED)) {
acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x100);
+ ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x100, NULL);
new_wlan_status = 0;
}
else if (sc->wlan_enable_if_radio_on && (wireless & HP_MASK_WLAN_RADIO)
&& !(wireless & HP_MASK_WLAN_ENABLED)) {
acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x101);
+ ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x101, NULL);
new_wlan_status = 1;
}
if (sc->bluetooth_disable_if_radio_off &&
!(wireless & HP_MASK_BLUETOOTH_RADIO) &&
(wireless & HP_MASK_BLUETOOTH_ENABLED)) {
acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x200);
+ ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x200, NULL);
new_bluetooth_status = 0;
}
else if (sc->bluetooth_enable_if_radio_on &&
(wireless & HP_MASK_BLUETOOTH_RADIO) &&
!(wireless & HP_MASK_BLUETOOTH_ENABLED)) {
acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x202);
+ ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x202, NULL);
new_bluetooth_status = 1;
}
if (sc->wwan_disable_if_radio_off &&
!(wireless & HP_MASK_WWAN_RADIO) &&
(wireless & HP_MASK_WWAN_ENABLED)) {
acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x400);
+ ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x400, NULL);
new_wwan_status = 0;
}
else if (sc->wwan_enable_if_radio_on &&
(wireless & HP_MASK_WWAN_RADIO) &&
!(wireless & HP_MASK_WWAN_ENABLED)) {
acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x404);
+ ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x404, NULL);
new_wwan_status = 1;
}
@@ -441,6 +474,11 @@ acpi_hp_identify(driver_t *driver, device_t parent)
if (device_find_child(parent, "acpi_hp", -1) != NULL)
return;
+ /* Check BIOS GUID to see whether system is compatible. */
+ if (!ACPI_WMI_PROVIDES_GUID_STRING(parent,
+ ACPI_HP_WMI_BIOS_GUID))
+ return;
+
if (BUS_ADD_CHILD(parent, 0, "acpi_hp", -1) == NULL)
device_printf(parent, "add acpi_hp child failed\n");
}
@@ -476,7 +514,7 @@ acpi_hp_attach(device_t dev)
sc->was_wwan_on_air = 0;
sc->cmi_detail = 0;
sc->cmi_order_size = -1;
- sc->verbose = 0;
+ sc->verbose = bootverbose;
memset(sc->cmi_order, 0, sizeof(sc->cmi_order));
sc->wmi_dev = device_get_parent(dev);
@@ -513,13 +551,17 @@ acpi_hp_attach(device_t dev)
sc->hpcmi_bufptr = -1;
}
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, NULL) == 0)
+ sc->has_wireless = 1;
+
ACPI_SERIAL_BEGIN(hp);
sc->sysctl_ctx = device_get_sysctl_ctx(dev);
sc->sysctl_tree = device_get_sysctl_tree(dev);
for (int i = 0; acpi_hp_sysctls[i].name != NULL; ++i) {
arg = 0;
- if ((!sc->has_notify &&
+ if (((!sc->has_notify || !sc->has_wireless) &&
(acpi_hp_sysctls[i].method ==
ACPI_HP_METHOD_WLAN_ENABLE_IF_RADIO_ON ||
acpi_hp_sysctls[i].method ==
@@ -577,8 +619,10 @@ acpi_hp_detach(device_t dev)
if (sc->has_cmi && sc->hpcmi_open_pid != 0)
return (EBUSY);
- if (sc->has_notify)
- ACPI_WMI_REMOVE_EVENT_HANDLER(dev, ACPI_HP_WMI_EVENT_GUID);
+ if (sc->has_notify) {
+ ACPI_WMI_REMOVE_EVENT_HANDLER(sc->wmi_dev,
+ ACPI_HP_WMI_EVENT_GUID);
+ }
if (sc->has_cmi) {
if (sc->hpcmi_bufptr != -1) {
@@ -630,18 +674,21 @@ acpi_hp_sysctl_get(struct acpi_hp_softc *sc, int method)
switch (method) {
case ACPI_HP_METHOD_WLAN_ENABLED:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val))
+ return (-EINVAL);
val = ((val & HP_MASK_WLAN_ENABLED) != 0);
break;
case ACPI_HP_METHOD_WLAN_RADIO:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val))
+ return (-EINVAL);
val = ((val & HP_MASK_WLAN_RADIO) != 0);
break;
case ACPI_HP_METHOD_WLAN_ON_AIR:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val))
+ return (-EINVAL);
val = ((val & HP_MASK_WLAN_ON_AIR) != 0);
break;
case ACPI_HP_METHOD_WLAN_ENABLE_IF_RADIO_ON:
@@ -651,18 +698,21 @@ acpi_hp_sysctl_get(struct acpi_hp_softc *sc, int method)
val = sc->wlan_disable_if_radio_off;
break;
case ACPI_HP_METHOD_BLUETOOTH_ENABLED:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val))
+ return (-EINVAL);
val = ((val & HP_MASK_BLUETOOTH_ENABLED) != 0);
break;
case ACPI_HP_METHOD_BLUETOOTH_RADIO:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val))
+ return (-EINVAL);
val = ((val & HP_MASK_BLUETOOTH_RADIO) != 0);
break;
case ACPI_HP_METHOD_BLUETOOTH_ON_AIR:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val))
+ return (-EINVAL);
val = ((val & HP_MASK_BLUETOOTH_ON_AIR) != 0);
break;
case ACPI_HP_METHOD_BLUETOOTH_ENABLE_IF_RADIO_ON:
@@ -672,18 +722,21 @@ acpi_hp_sysctl_get(struct acpi_hp_softc *sc, int method)
val = sc->bluetooth_disable_if_radio_off;
break;
case ACPI_HP_METHOD_WWAN_ENABLED:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val))
+ return (-EINVAL);
val = ((val & HP_MASK_WWAN_ENABLED) != 0);
break;
case ACPI_HP_METHOD_WWAN_RADIO:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val))
+ return (-EINVAL);
val = ((val & HP_MASK_WWAN_RADIO) != 0);
break;
case ACPI_HP_METHOD_WWAN_ON_AIR:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val))
+ return (-EINVAL);
val = ((val & HP_MASK_WWAN_ON_AIR) != 0);
break;
case ACPI_HP_METHOD_WWAN_ENABLE_IF_RADIO_ON:
@@ -693,20 +746,24 @@ acpi_hp_sysctl_get(struct acpi_hp_softc *sc, int method)
val = sc->wwan_disable_if_radio_off;
break;
case ACPI_HP_METHOD_ALS:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_ALS_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_ALS_COMMAND, 0, 0, &val))
+ return (-EINVAL);
break;
case ACPI_HP_METHOD_DISPLAY:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_DISPLAY_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_DISPLAY_COMMAND, 0, 0, &val))
+ return (-EINVAL);
break;
case ACPI_HP_METHOD_HDDTEMP:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_HDDTEMP_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_HDDTEMP_COMMAND, 0, 0, &val))
+ return (-EINVAL);
break;
case ACPI_HP_METHOD_DOCK:
- val = acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_DOCK_COMMAND, 0, 0);
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_DOCK_COMMAND, 0, 0, &val))
+ return (-EINVAL);
break;
case ACPI_HP_METHOD_CMI_DETAIL:
val = sc->cmi_detail;
@@ -732,9 +789,11 @@ acpi_hp_sysctl_set(struct acpi_hp_softc *sc, int method, int arg, int oldarg)
if (arg != oldarg) {
switch (method) {
case ACPI_HP_METHOD_WLAN_ENABLED:
- return (acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 1,
- arg?0x101:0x100));
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 1,
+ arg?0x101:0x100, NULL))
+ return (-EINVAL);
+ break;
case ACPI_HP_METHOD_WLAN_ENABLE_IF_RADIO_ON:
sc->wlan_enable_if_radio_on = arg;
acpi_hp_evaluate_auto_on_off(sc);
@@ -744,9 +803,11 @@ acpi_hp_sysctl_set(struct acpi_hp_softc *sc, int method, int arg, int oldarg)
acpi_hp_evaluate_auto_on_off(sc);
break;
case ACPI_HP_METHOD_BLUETOOTH_ENABLED:
- return (acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 1,
- arg?0x202:0x200));
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 1,
+ arg?0x202:0x200, NULL))
+ return (-EINVAL);
+ break;
case ACPI_HP_METHOD_BLUETOOTH_ENABLE_IF_RADIO_ON:
sc->bluetooth_enable_if_radio_on = arg;
acpi_hp_evaluate_auto_on_off(sc);
@@ -756,9 +817,11 @@ acpi_hp_sysctl_set(struct acpi_hp_softc *sc, int method, int arg, int oldarg)
acpi_hp_evaluate_auto_on_off(sc);
break;
case ACPI_HP_METHOD_WWAN_ENABLED:
- return (acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_WIRELESS_COMMAND, 1,
- arg?0x404:0x400));
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_WIRELESS_COMMAND, 1,
+ arg?0x404:0x400, NULL))
+ return (-EINVAL);
+ break;
case ACPI_HP_METHOD_WWAN_ENABLE_IF_RADIO_ON:
sc->wwan_enable_if_radio_on = arg?1:0;
acpi_hp_evaluate_auto_on_off(sc);
@@ -768,9 +831,10 @@ acpi_hp_sysctl_set(struct acpi_hp_softc *sc, int method, int arg, int oldarg)
acpi_hp_evaluate_auto_on_off(sc);
break;
case ACPI_HP_METHOD_ALS:
- return (acpi_hp_exec_wmi_command(sc->wmi_dev,
- ACPI_HP_WMI_ALS_COMMAND, 1,
- arg?1:0));
+ if (acpi_hp_exec_wmi_command(sc->wmi_dev,
+ ACPI_HP_WMI_ALS_COMMAND, 1, arg?1:0, NULL))
+ return (-EINVAL);
+ break;
case ACPI_HP_METHOD_CMI_DETAIL:
sc->cmi_detail = arg;
if ((arg & ACPI_HP_CMI_DETAIL_SHOW_MAX_INSTANCE) !=
@@ -806,26 +870,32 @@ acpi_hp_notify(ACPI_HANDLE h, UINT32 notify, void *context)
ACPI_WMI_GET_EVENT_DATA(sc->wmi_dev, notify, &response);
obj = (ACPI_OBJECT*) response.Pointer;
if (obj && obj->Type == ACPI_TYPE_BUFFER && obj->Buffer.Length == 8) {
- if (*((UINT8 *) obj->Buffer.Pointer) == 0x5) {
+ switch (*((UINT8 *) obj->Buffer.Pointer)) {
+ case ACPI_HP_EVENT_WIRELESS:
acpi_hp_evaluate_auto_on_off(sc);
+ break;
+ default:
+ if (sc->verbose) {
+ device_printf(sc->dev, "Event %02x\n",
+ *((UINT8 *) obj->Buffer.Pointer));
+ }
+ break;
}
}
acpi_hp_free_buffer(&response);
}
static int
-acpi_hp_exec_wmi_command(device_t wmi_dev, int command, int is_write, int val)
+acpi_hp_exec_wmi_command(device_t wmi_dev, int command, int is_write,
+ int val, int *retval)
{
- UINT32 params[5] = { 0x55434553,
- is_write?2:1,
- command,
- is_write?4:0,
- val};
+ UINT32 params[4+32] = { 0x55434553, is_write ? 2 : 1,
+ command, 4, val};
UINT32* result;
ACPI_OBJECT *obj;
ACPI_BUFFER in = { sizeof(params), &params };
ACPI_BUFFER out = { ACPI_ALLOCATE_BUFFER, NULL };
- int retval;
+ int res;
if (ACPI_FAILURE(ACPI_WMI_EVALUATE_CALL(wmi_dev, ACPI_HP_WMI_BIOS_GUID,
0, 0x3, &in, &out))) {
@@ -838,13 +908,12 @@ acpi_hp_exec_wmi_command(device_t wmi_dev, int command, int is_write, int val)
return (-EINVAL);
}
result = (UINT32*) obj->Buffer.Pointer;
- retval = result[2];
- if (result[1] > 0) {
- retval = result[1];
- }
+ res = result[1];
+ if (res == 0 && retval != NULL)
+ *retval = result[2];
acpi_hp_free_buffer(&out);
- return (retval);
+ return (res);
}
static __inline char*
@@ -909,81 +978,91 @@ acpi_hp_get_cmi_block(device_t wmi_dev, const char* guid, UINT8 instance,
return (-EINVAL);
}
- if (obj->Package.Count >= 8 &&
- obj->Package.Elements[7].Type == ACPI_TYPE_INTEGER) {
- valuebase = 8 + obj->Package.Elements[7].Integer.Value;
+ /* Check if first 6 bytes matches our expectations. */
+ if (obj->Package.Count < 8 ||
+ obj->Package.Elements[0].Type != ACPI_TYPE_STRING ||
+ obj->Package.Elements[1].Type != ACPI_TYPE_STRING ||
+ obj->Package.Elements[2].Type != ACPI_TYPE_STRING ||
+ obj->Package.Elements[3].Type != ACPI_TYPE_INTEGER ||
+ obj->Package.Elements[4].Type != ACPI_TYPE_INTEGER ||
+ obj->Package.Elements[5].Type != ACPI_TYPE_INTEGER ||
+ obj->Package.Elements[6].Type != ACPI_TYPE_INTEGER ||
+ obj->Package.Elements[7].Type != ACPI_TYPE_INTEGER) {
+ acpi_hp_free_buffer(&out);
+ return (-EINVAL);
}
- /* check if this matches our expectations based on limited knowledge */
- if (valuebase > 7 && obj->Package.Count > valuebase + 1 &&
- obj->Package.Elements[0].Type == ACPI_TYPE_STRING &&
- obj->Package.Elements[1].Type == ACPI_TYPE_STRING &&
- obj->Package.Elements[2].Type == ACPI_TYPE_STRING &&
- obj->Package.Elements[3].Type == ACPI_TYPE_INTEGER &&
- obj->Package.Elements[4].Type == ACPI_TYPE_INTEGER &&
- obj->Package.Elements[5].Type == ACPI_TYPE_INTEGER &&
- obj->Package.Elements[6].Type == ACPI_TYPE_INTEGER &&
- obj->Package.Elements[valuebase].Type == ACPI_TYPE_STRING &&
- obj->Package.Elements[valuebase+1].Type == ACPI_TYPE_INTEGER &&
- obj->Package.Count > valuebase +
- obj->Package.Elements[valuebase+1].Integer.Value
- ) {
- enumbase = valuebase + 1;
- if (detail & ACPI_HP_CMI_DETAIL_PATHS) {
- strlcat(outbuf, acpi_hp_get_string_from_object(
- &obj->Package.Elements[2], string_buffer, size),
- outsize);
- outlen += 48;
- while (strlen(outbuf) < outlen)
- strlcat(outbuf, " ", outsize);
- }
- strlcat(outbuf, acpi_hp_get_string_from_object(
- &obj->Package.Elements[0], string_buffer, size),
- outsize);
- outlen += 43;
- while (strlen(outbuf) < outlen)
- strlcat(outbuf, " ", outsize);
+ /* Skip prerequisites and optionally array. */
+ valuebase = 8 + obj->Package.Elements[7].Integer.Value;
+ if (obj->Package.Count <= valuebase) {
+ acpi_hp_free_buffer(&out);
+ return (-EINVAL);
+ }
+ if (obj->Package.Elements[valuebase].Type == ACPI_TYPE_INTEGER)
+ valuebase += 1 + obj->Package.Elements[valuebase].Integer.Value;
+
+ /* Check if we have value and enum. */
+ if (obj->Package.Count <= valuebase + 1 ||
+ obj->Package.Elements[valuebase].Type != ACPI_TYPE_STRING ||
+ obj->Package.Elements[valuebase+1].Type != ACPI_TYPE_INTEGER) {
+ acpi_hp_free_buffer(&out);
+ return (-EINVAL);
+ }
+ enumbase = valuebase + 1;
+ if (obj->Package.Count <= valuebase +
+ obj->Package.Elements[enumbase].Integer.Value) {
+ acpi_hp_free_buffer(&out);
+ return (-EINVAL);
+ }
+
+ if (detail & ACPI_HP_CMI_DETAIL_PATHS) {
strlcat(outbuf, acpi_hp_get_string_from_object(
- &obj->Package.Elements[valuebase], string_buffer,
- size),
- outsize);
- outlen += 21;
+ &obj->Package.Elements[2], string_buffer, size), outsize);
+ outlen += 48;
while (strlen(outbuf) < outlen)
strlcat(outbuf, " ", outsize);
- for (i = 0; i < strlen(outbuf); ++i)
- if (outbuf[i] == '\\')
- outbuf[i] = '/';
- if (detail & ACPI_HP_CMI_DETAIL_ENUMS) {
- for (i = enumbase + 1; i < enumbase + 1 +
- obj->Package.Elements[enumbase].Integer.Value;
- ++i) {
- acpi_hp_get_string_from_object(
- &obj->Package.Elements[i], string_buffer,
- size);
- if (strlen(string_buffer) > 1 ||
- (strlen(string_buffer) == 1 &&
- string_buffer[0] != ' ')) {
- if (has_enums)
- strlcat(outbuf, "/", outsize);
- else
- strlcat(outbuf, " (", outsize);
- strlcat(outbuf, string_buffer, outsize);
- has_enums = 1;
- }
+ }
+ strlcat(outbuf, acpi_hp_get_string_from_object(
+ &obj->Package.Elements[0], string_buffer, size), outsize);
+ outlen += 43;
+ while (strlen(outbuf) < outlen)
+ strlcat(outbuf, " ", outsize);
+ strlcat(outbuf, acpi_hp_get_string_from_object(
+ &obj->Package.Elements[valuebase], string_buffer, size), outsize);
+ outlen += 21;
+ while (strlen(outbuf) < outlen)
+ strlcat(outbuf, " ", outsize);
+ for (i = 0; i < strlen(outbuf); ++i)
+ if (outbuf[i] == '\\')
+ outbuf[i] = '/';
+ if (detail & ACPI_HP_CMI_DETAIL_ENUMS) {
+ for (i = enumbase + 1; i < enumbase + 1 +
+ obj->Package.Elements[enumbase].Integer.Value; ++i) {
+ acpi_hp_get_string_from_object(
+ &obj->Package.Elements[i], string_buffer, size);
+ if (strlen(string_buffer) > 1 ||
+ (strlen(string_buffer) == 1 &&
+ string_buffer[0] != ' ')) {
+ if (has_enums)
+ strlcat(outbuf, "/", outsize);
+ else
+ strlcat(outbuf, " (", outsize);
+ strlcat(outbuf, string_buffer, outsize);
+ has_enums = 1;
}
}
- if (has_enums)
- strlcat(outbuf, ")", outsize);
- if (detail & ACPI_HP_CMI_DETAIL_FLAGS) {
- strlcat(outbuf, obj->Package.Elements[3].Integer.Value?
- " [ReadOnly]":"", outsize);
- strlcat(outbuf, obj->Package.Elements[4].Integer.Value?
- "":" [NOUI]", outsize);
- strlcat(outbuf, obj->Package.Elements[5].Integer.Value?
- " [RPP]":"", outsize);
- }
- *sequence = (UINT32) obj->Package.Elements[6].Integer.Value;
}
+ if (has_enums)
+ strlcat(outbuf, ")", outsize);
+ if (detail & ACPI_HP_CMI_DETAIL_FLAGS) {
+ strlcat(outbuf, obj->Package.Elements[3].Integer.Value ?
+ " [ReadOnly]" : "", outsize);
+ strlcat(outbuf, obj->Package.Elements[4].Integer.Value ?
+ "" : " [NOUI]", outsize);
+ strlcat(outbuf, obj->Package.Elements[5].Integer.Value ?
+ " [RPP]" : "", outsize);
+ }
+ *sequence = (UINT32) obj->Package.Elements[6].Integer.Value;
acpi_hp_free_buffer(&out);
return (0);
diff --git a/sys/dev/bhnd/bcma/bcma.c b/sys/dev/bhnd/bcma/bcma.c
index 08808955ba0e..7b4be6cb61b2 100644
--- a/sys/dev/bhnd/bcma/bcma.c
+++ b/sys/dev/bhnd/bcma/bcma.c
@@ -274,7 +274,7 @@ bcma_is_hw_suspended(device_t dev, device_t child)
return (true);
}
- if (rst & BMCA_DMP_RC_RESET)
+ if (rst & BCMA_DMP_RC_RESET)
return (true);
/* Is core clocked? */
@@ -367,11 +367,11 @@ bcma_suspend_hw(device_t dev, device_t child)
/* Already in reset? */
rst = bhnd_bus_read_4(r, BCMA_DMP_RESETCTRL);
- if (rst & BMCA_DMP_RC_RESET)
+ if (rst & BCMA_DMP_RC_RESET)
return (0);
/* Put core into reset */
- if ((error = bcma_dmp_write_reset(child, dinfo, BMCA_DMP_RC_RESET)))
+ if ((error = bcma_dmp_write_reset(child, dinfo, BCMA_DMP_RC_RESET)))
return (error);
/* Clear core flags */
diff --git a/sys/dev/bhnd/bcma/bcma_dmp.h b/sys/dev/bhnd/bcma/bcma_dmp.h
index 0fd41a7a4f24..36f84f1388d2 100644
--- a/sys/dev/bhnd/bcma/bcma_dmp.h
+++ b/sys/dev/bhnd/bcma/bcma_dmp.h
@@ -252,7 +252,7 @@
#define BCMA_DMP_IOST_MASK 0x0000FFFF
/* resetctrl */
-#define BMCA_DMP_RC_RESET 0x00000001
+#define BCMA_DMP_RC_RESET 0x00000001
/* config */
#define BCMA_DMP_CFG_OOB 0x00000020
diff --git a/sys/dev/bnxt/bnxt.h b/sys/dev/bnxt/bnxt.h
new file mode 100644
index 000000000000..dee88885e8a8
--- /dev/null
+++ b/sys/dev/bnxt/bnxt.h
@@ -0,0 +1,568 @@
+/*-
+ * Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 _BNXT_H
+#define _BNXT_H
+
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <sys/bus_dma.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/iflib.h>
+
+#include "hsi_struct_def.h"
+
+/* PCI IDs */
+#define BROADCOM_VENDOR_ID 0x14E4
+
+#define BCM57301 0x16c8
+#define BCM57302 0x16c9
+#define BCM57304 0x16ca
+#define BCM57402 0x16d0
+#define BCM57404 0x16d1
+#define BCM57406 0x16d2
+#define BCM57402_NPAR 0x16d4
+#define BCM57407 0x16d5
+#define BCM57404_NPAR 0x16e7
+#define BCM57406_NPAR 0x16e8
+#define BCM57407_SFP 0x16e9
+#define BCM57304_VF 0x16cb
+#define BCM57404_VF 0x16d3
+
+#define CSUM_OFFLOAD (CSUM_IP_TSO|CSUM_IP6_TSO|CSUM_IP| \
+ CSUM_IP_UDP|CSUM_IP_TCP|CSUM_IP_SCTP| \
+ CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP)
+
+#define BNXT_MAX_MTU 9000
+
+/* Completion related defines */
+#define CMP_VALID(cmp, v_bit) \
+ ((!!(((struct cmpl_base *)(cmp))->info3_v & htole32(CMPL_BASE_V))) == !!(v_bit) )
+
+#define NEXT_CP_CONS_V(ring, cons, v_bit) do { \
+ if (__predict_false(++(cons) == (ring)->ring_size)) \
+ ((cons) = 0, (v_bit) = !v_bit); \
+} while (0)
+
+#define RING_NEXT(ring, idx) (__predict_false(idx + 1 == (ring)->ring_size) ? \
+ 0 : idx + 1)
+
+#define CMPL_PREFETCH_NEXT(cpr, idx) \
+ __builtin_prefetch(&((struct cmpl_base *)(cpr)->ring.vaddr)[((idx) +\
+ (CACHE_LINE_SIZE / sizeof(struct cmpl_base))) & \
+ ((cpr)->ring.ring_size - 1)])
+
+/*
+ * If we update the index, a write barrier is needed after the write to ensure
+ * the completion ring has space before the RX/TX ring does. Since we can't
+ * make the RX and AG doorbells covered by the same barrier without remapping
+ * MSI-X vectors, we create the barrier over the enture doorbell bar.
+ * TODO: Remap the MSI-X vectors to allow a barrier to only cover the doorbells
+ * for a single ring group.
+ *
+ * A barrier of just the size of the write is used to ensure the ordering
+ * remains correct and no writes are lost.
+ */
+#define BNXT_CP_DISABLE_DB(ring) do { \
+ bus_space_barrier((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \
+ BUS_SPACE_BARRIER_WRITE); \
+ bus_space_barrier((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, 0, \
+ (ring)->softc->doorbell_bar.size, BUS_SPACE_BARRIER_WRITE); \
+ bus_space_write_4((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, (ring)->doorbell, \
+ htole32(CMPL_DOORBELL_KEY_CMPL | CMPL_DOORBELL_MASK)); \
+} while (0)
+
+#define BNXT_CP_ENABLE_DB(ring) do { \
+ bus_space_barrier((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \
+ BUS_SPACE_BARRIER_WRITE); \
+ bus_space_barrier((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, 0, \
+ (ring)->softc->doorbell_bar.size, BUS_SPACE_BARRIER_WRITE); \
+ bus_space_write_4((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, (ring)->doorbell, \
+ htole32(CMPL_DOORBELL_KEY_CMPL)); \
+} while (0)
+
+#define BNXT_CP_IDX_ENABLE_DB(ring, cons) do { \
+ bus_space_barrier((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \
+ BUS_SPACE_BARRIER_WRITE); \
+ bus_space_write_4((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, (ring)->doorbell, \
+ htole32(CMPL_DOORBELL_KEY_CMPL | CMPL_DOORBELL_IDX_VALID | \
+ (cons))); \
+ bus_space_barrier((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, 0, \
+ (ring)->softc->doorbell_bar.size, BUS_SPACE_BARRIER_WRITE); \
+} while (0)
+
+#define BNXT_CP_IDX_DISABLE_DB(ring, cons) do { \
+ bus_space_barrier((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \
+ BUS_SPACE_BARRIER_WRITE); \
+ bus_space_write_4((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, (ring)->doorbell, \
+ htole32(CMPL_DOORBELL_KEY_CMPL | CMPL_DOORBELL_IDX_VALID | \
+ CMPL_DOORBELL_MASK | (cons))); \
+ bus_space_barrier((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, 0, \
+ (ring)->softc->doorbell_bar.size, BUS_SPACE_BARRIER_WRITE); \
+} while (0)
+
+#define BNXT_TX_DB(ring, idx) do { \
+ bus_space_barrier((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \
+ BUS_SPACE_BARRIER_WRITE); \
+ bus_space_write_4( \
+ (ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, \
+ (ring)->doorbell, htole32(TX_DOORBELL_KEY_TX | (idx))); \
+} while (0)
+
+#define BNXT_RX_DB(ring, idx) do { \
+ bus_space_barrier((ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \
+ BUS_SPACE_BARRIER_WRITE); \
+ bus_space_write_4( \
+ (ring)->softc->doorbell_bar.tag, \
+ (ring)->softc->doorbell_bar.handle, \
+ (ring)->doorbell, htole32(RX_DOORBELL_KEY_RX | (idx))); \
+} while (0)
+
+/* Lock macros */
+#define BNXT_HWRM_LOCK_INIT(_softc, _name) \
+ mtx_init(&(_softc)->hwrm_lock, _name, "BNXT HWRM Lock", MTX_DEF)
+#define BNXT_HWRM_LOCK(_softc) mtx_lock(&(_softc)->hwrm_lock)
+#define BNXT_HWRM_UNLOCK(_softc) mtx_unlock(&(_softc)->hwrm_lock)
+#define BNXT_HWRM_LOCK_DESTROY(_softc) mtx_destroy(&(_softc)->hwrm_lock)
+#define BNXT_HWRM_LOCK_ASSERT(_softc) mtx_assert(&(_softc)->hwrm_lock, \
+ MA_OWNED)
+
+/* Chip info */
+#define BNXT_TSO_SIZE UINT16_MAX
+
+/* NVRAM access */
+enum bnxt_nvm_directory_type {
+ BNX_DIR_TYPE_UNUSED = 0,
+ BNX_DIR_TYPE_PKG_LOG = 1,
+ BNX_DIR_TYPE_UPDATE = 2,
+ BNX_DIR_TYPE_CHIMP_PATCH = 3,
+ BNX_DIR_TYPE_BOOTCODE = 4,
+ BNX_DIR_TYPE_VPD = 5,
+ BNX_DIR_TYPE_EXP_ROM_MBA = 6,
+ BNX_DIR_TYPE_AVS = 7,
+ BNX_DIR_TYPE_PCIE = 8,
+ BNX_DIR_TYPE_PORT_MACRO = 9,
+ BNX_DIR_TYPE_APE_FW = 10,
+ BNX_DIR_TYPE_APE_PATCH = 11,
+ BNX_DIR_TYPE_KONG_FW = 12,
+ BNX_DIR_TYPE_KONG_PATCH = 13,
+ BNX_DIR_TYPE_BONO_FW = 14,
+ BNX_DIR_TYPE_BONO_PATCH = 15,
+ BNX_DIR_TYPE_TANG_FW = 16,
+ BNX_DIR_TYPE_TANG_PATCH = 17,
+ BNX_DIR_TYPE_BOOTCODE_2 = 18,
+ BNX_DIR_TYPE_CCM = 19,
+ BNX_DIR_TYPE_PCI_CFG = 20,
+ BNX_DIR_TYPE_TSCF_UCODE = 21,
+ BNX_DIR_TYPE_ISCSI_BOOT = 22,
+ BNX_DIR_TYPE_ISCSI_BOOT_IPV6 = 24,
+ BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6 = 25,
+ BNX_DIR_TYPE_ISCSI_BOOT_CFG6 = 26,
+ BNX_DIR_TYPE_EXT_PHY = 27,
+ BNX_DIR_TYPE_SHARED_CFG = 40,
+ BNX_DIR_TYPE_PORT_CFG = 41,
+ BNX_DIR_TYPE_FUNC_CFG = 42,
+ BNX_DIR_TYPE_MGMT_CFG = 48,
+ BNX_DIR_TYPE_MGMT_DATA = 49,
+ BNX_DIR_TYPE_MGMT_WEB_DATA = 50,
+ BNX_DIR_TYPE_MGMT_WEB_META = 51,
+ BNX_DIR_TYPE_MGMT_EVENT_LOG = 52,
+ BNX_DIR_TYPE_MGMT_AUDIT_LOG = 53
+};
+
+enum bnxnvm_pkglog_field_index {
+ BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0,
+ BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1,
+ BNX_PKG_LOG_FIELD_IDX_PKG_VERSION = 2,
+ BNX_PKG_LOG_FIELD_IDX_PKG_TIMESTAMP = 3,
+ BNX_PKG_LOG_FIELD_IDX_PKG_CHECKSUM = 4,
+ BNX_PKG_LOG_FIELD_IDX_INSTALLED_ITEMS = 5,
+ BNX_PKG_LOG_FIELD_IDX_INSTALLED_MASK = 6
+};
+
+#define BNX_DIR_ORDINAL_FIRST 0
+#define BNX_DIR_EXT_NONE 0
+
+struct bnxt_bar_info {
+ struct resource *res;
+ bus_space_tag_t tag;
+ bus_space_handle_t handle;
+ bus_size_t size;
+ int rid;
+};
+
+struct bnxt_link_info {
+ uint8_t media_type;
+ uint8_t transceiver;
+ uint8_t phy_addr;
+ uint8_t phy_link_status;
+ uint8_t wire_speed;
+ uint8_t loop_back;
+ uint8_t link_up;
+ uint8_t last_link_up;
+ uint8_t duplex;
+ uint8_t last_duplex;
+ uint8_t pause;
+ uint8_t last_pause;
+ uint8_t auto_pause;
+ uint8_t force_pause;
+ uint8_t duplex_setting;
+ uint8_t auto_mode;
+#define PHY_VER_LEN 3
+ uint8_t phy_ver[PHY_VER_LEN];
+ uint8_t phy_type;
+ uint16_t link_speed;
+ uint16_t support_speeds;
+ uint16_t auto_link_speeds;
+ uint16_t auto_link_speed;
+ uint16_t force_link_speed;
+ uint32_t preemphasis;
+
+ /* copy of requested setting */
+ uint8_t autoneg;
+#define BNXT_AUTONEG_SPEED 1
+#define BNXT_AUTONEG_FLOW_CTRL 2
+ uint8_t req_duplex;
+ uint8_t req_flow_ctrl;
+ uint16_t req_link_speed;
+};
+
+enum bnxt_cp_type {
+ BNXT_DEFAULT,
+ BNXT_TX,
+ BNXT_RX,
+ BNXT_SHARED
+};
+
+struct bnxt_cos_queue {
+ uint8_t id;
+ uint8_t profile;
+};
+
+struct bnxt_func_info {
+ uint32_t fw_fid;
+ uint8_t mac_addr[ETHER_ADDR_LEN];
+ uint16_t max_rsscos_ctxs;
+ uint16_t max_cp_rings;
+ uint16_t max_tx_rings;
+ uint16_t max_rx_rings;
+ uint16_t max_hw_ring_grps;
+ uint16_t max_irqs;
+ uint16_t max_l2_ctxs;
+ uint16_t max_vnics;
+ uint16_t max_stat_ctxs;
+};
+
+struct bnxt_pf_info {
+#define BNXT_FIRST_PF_FID 1
+#define BNXT_FIRST_VF_FID 128
+ uint8_t port_id;
+ uint32_t first_vf_id;
+ uint16_t active_vfs;
+ uint16_t max_vfs;
+ uint32_t max_encap_records;
+ uint32_t max_decap_records;
+ uint32_t max_tx_em_flows;
+ uint32_t max_tx_wm_flows;
+ uint32_t max_rx_em_flows;
+ uint32_t max_rx_wm_flows;
+ unsigned long *vf_event_bmap;
+ uint16_t hwrm_cmd_req_pages;
+ void *hwrm_cmd_req_addr[4];
+ bus_addr_t hwrm_cmd_req_dma_addr[4];
+};
+
+struct bnxt_vf_info {
+ uint16_t fw_fid;
+ uint8_t mac_addr[ETHER_ADDR_LEN];
+ uint16_t max_rsscos_ctxs;
+ uint16_t max_cp_rings;
+ uint16_t max_tx_rings;
+ uint16_t max_rx_rings;
+ uint16_t max_hw_ring_grps;
+ uint16_t max_l2_ctxs;
+ uint16_t max_irqs;
+ uint16_t max_vnics;
+ uint16_t max_stat_ctxs;
+ uint32_t vlan;
+#define BNXT_VF_QOS 0x1
+#define BNXT_VF_SPOOFCHK 0x2
+#define BNXT_VF_LINK_FORCED 0x4
+#define BNXT_VF_LINK_UP 0x8
+ uint32_t flags;
+ uint32_t func_flags; /* func cfg flags */
+ uint32_t min_tx_rate;
+ uint32_t max_tx_rate;
+ void *hwrm_cmd_req_addr;
+ bus_addr_t hwrm_cmd_req_dma_addr;
+};
+
+#define BNXT_FLAG_VF (1<<1)
+
+#define BNXT_PF(softc) (!((softc)->flags & BNXT_FLAG_VF))
+#define BNXT_VF(softc) ((softc)->flags & BNXT_FLAG_VF)
+
+struct bnxt_vlan_tag {
+ SLIST_ENTRY(bnxt_vlan_tag) next;
+ uint16_t tpid;
+ uint16_t tag;
+};
+
+struct bnxt_vnic_info {
+ uint16_t id;
+ uint16_t def_ring_grp;
+ uint16_t cos_rule;
+ uint16_t lb_rule;
+ uint16_t mru;
+
+ uint32_t rx_mask;
+ bool vlan_only;
+ struct iflib_dma_info mc_list;
+ int mc_list_count;
+#define BNXT_MAX_MC_ADDRS 16
+
+ uint32_t flags;
+#define BNXT_VNIC_FLAG_DEFAULT 0x01
+#define BNXT_VNIC_FLAG_BD_STALL 0x02
+#define BNXT_VNIC_FLAG_VLAN_STRIP 0x04
+
+ uint64_t filter_id;
+ uint32_t flow_id;
+
+ uint16_t rss_id;
+ uint32_t rss_hash_type;
+ uint8_t rss_hash_key[HW_HASH_KEY_SIZE];
+ struct iflib_dma_info rss_hash_key_tbl;
+ struct iflib_dma_info rss_grp_tbl;
+ SLIST_HEAD(vlan_head, bnxt_vlan_tag) vlan_tags;
+ struct iflib_dma_info vlan_tag_list;
+};
+
+struct bnxt_grp_info {
+ uint16_t stats_ctx;
+ uint16_t grp_id;
+ uint16_t rx_ring_id;
+ uint16_t cp_ring_id;
+ uint16_t ag_ring_id;
+};
+
+struct bnxt_ring {
+ uint64_t paddr;
+ vm_offset_t doorbell;
+ caddr_t vaddr;
+ struct bnxt_softc *softc;
+ uint32_t ring_size; /* Must be a power of two */
+ uint16_t id; /* Logical ID */
+ uint16_t phys_id;
+};
+
+struct bnxt_cp_ring {
+ struct bnxt_ring ring;
+ struct if_irq irq;
+ uint32_t cons;
+ bool v_bit; /* Value of valid bit */
+ struct ctx_hw_stats *stats;
+ uint32_t stats_ctx_id;
+ uint32_t last_idx; /* Used by RX rings only
+ * set to the last read pidx
+ */
+};
+
+struct bnxt_full_tpa_start {
+ struct rx_tpa_start_cmpl low;
+ struct rx_tpa_start_cmpl_hi high;
+};
+
+/* All the version information for the part */
+#define BNXT_VERSTR_SIZE (3*3+2+1) /* ie: "255.255.255\0" */
+#define BNXT_NAME_SIZE 17
+struct bnxt_ver_info {
+ uint8_t hwrm_if_major;
+ uint8_t hwrm_if_minor;
+ uint8_t hwrm_if_update;
+ char hwrm_if_ver[BNXT_VERSTR_SIZE];
+ char driver_hwrm_if_ver[BNXT_VERSTR_SIZE];
+ char hwrm_fw_ver[BNXT_VERSTR_SIZE];
+ char mgmt_fw_ver[BNXT_VERSTR_SIZE];
+ char netctrl_fw_ver[BNXT_VERSTR_SIZE];
+ char roce_fw_ver[BNXT_VERSTR_SIZE];
+ char phy_ver[BNXT_VERSTR_SIZE];
+ char pkg_ver[64];
+
+ char hwrm_fw_name[BNXT_NAME_SIZE];
+ char mgmt_fw_name[BNXT_NAME_SIZE];
+ char netctrl_fw_name[BNXT_NAME_SIZE];
+ char roce_fw_name[BNXT_NAME_SIZE];
+ char phy_vendor[BNXT_NAME_SIZE];
+ char phy_partnumber[BNXT_NAME_SIZE];
+
+ uint16_t chip_num;
+ uint8_t chip_rev;
+ uint8_t chip_metal;
+ uint8_t chip_bond_id;
+ uint8_t chip_type;
+
+ uint8_t hwrm_min_major;
+ uint8_t hwrm_min_minor;
+ uint8_t hwrm_min_update;
+
+ struct sysctl_ctx_list ver_ctx;
+ struct sysctl_oid *ver_oid;
+};
+
+struct bnxt_nvram_info {
+ uint16_t mfg_id;
+ uint16_t device_id;
+ uint32_t sector_size;
+ uint32_t size;
+ uint32_t reserved_size;
+ uint32_t available_size;
+
+ struct sysctl_ctx_list nvm_ctx;
+ struct sysctl_oid *nvm_oid;
+};
+
+struct bnxt_softc {
+ device_t dev;
+ if_ctx_t ctx;
+ if_softc_ctx_t scctx;
+ if_shared_ctx_t sctx;
+ struct ifmedia *media;
+
+ struct bnxt_bar_info hwrm_bar;
+ struct bnxt_bar_info doorbell_bar;
+ struct bnxt_link_info link_info;
+#define BNXT_FLAG_NPAR 1
+ uint32_t flags;
+ uint32_t total_msix;
+
+ struct bnxt_func_info func;
+ struct bnxt_pf_info pf;
+ struct bnxt_vf_info vf;
+
+ uint16_t hwrm_cmd_seq;
+ uint32_t hwrm_cmd_timeo; /* milliseconds */
+ struct iflib_dma_info hwrm_cmd_resp;
+ /* Interrupt info for HWRM */
+ struct if_irq irq;
+ struct mtx hwrm_lock;
+ uint16_t hwrm_max_req_len;
+
+#define BNXT_MAX_QUEUE 8
+ uint8_t max_tc;
+ struct bnxt_cos_queue q_info[BNXT_MAX_QUEUE];
+
+ struct iflib_dma_info hw_rx_port_stats;
+ struct iflib_dma_info hw_tx_port_stats;
+ struct rx_port_stats *rx_port_stats;
+ struct tx_port_stats *tx_port_stats;
+
+ int num_cp_rings;
+
+ struct bnxt_ring *tx_rings;
+ struct bnxt_cp_ring *tx_cp_rings;
+ struct iflib_dma_info tx_stats;
+ int ntxqsets;
+
+ struct bnxt_vnic_info vnic_info;
+ struct bnxt_ring *ag_rings;
+ struct bnxt_ring *rx_rings;
+ struct bnxt_cp_ring *rx_cp_rings;
+ struct bnxt_grp_info *grp_info;
+ struct iflib_dma_info rx_stats;
+ int nrxqsets;
+
+ struct bnxt_cp_ring def_cp_ring;
+ struct iflib_dma_info def_cp_ring_mem;
+ struct grouptask def_cp_task;
+
+ struct sysctl_ctx_list hw_stats;
+ struct sysctl_oid *hw_stats_oid;
+
+ struct bnxt_full_tpa_start *tpa_start;
+ struct bnxt_ver_info *ver_info;
+ struct bnxt_nvram_info *nvm_info;
+};
+
+struct bnxt_filter_info {
+ STAILQ_ENTRY(bnxt_filter_info) next;
+ uint64_t fw_l2_filter_id;
+#define INVALID_MAC_INDEX ((uint16_t)-1)
+ uint16_t mac_index;
+
+ /* Filter Characteristics */
+ uint32_t flags;
+ uint32_t enables;
+ uint8_t l2_addr[ETHER_ADDR_LEN];
+ uint8_t l2_addr_mask[ETHER_ADDR_LEN];
+ uint16_t l2_ovlan;
+ uint16_t l2_ovlan_mask;
+ uint16_t l2_ivlan;
+ uint16_t l2_ivlan_mask;
+ uint8_t t_l2_addr[ETHER_ADDR_LEN];
+ uint8_t t_l2_addr_mask[ETHER_ADDR_LEN];
+ uint16_t t_l2_ovlan;
+ uint16_t t_l2_ovlan_mask;
+ uint16_t t_l2_ivlan;
+ uint16_t t_l2_ivlan_mask;
+ uint8_t tunnel_type;
+ uint16_t mirror_vnic_id;
+ uint32_t vni;
+ uint8_t pri_hint;
+ uint64_t l2_filter_id_hint;
+};
+
+/* Function declarations */
+void bnxt_report_link(struct bnxt_softc *softc);
+bool bnxt_check_hwrm_version(struct bnxt_softc *softc);
+
+#endif /* _BNXT_H */
diff --git a/sys/dev/bnxt/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_hwrm.c
new file mode 100644
index 000000000000..a6c5cf17b1aa
--- /dev/null
+++ b/sys/dev/bnxt/bnxt_hwrm.c
@@ -0,0 +1,1485 @@
+/*-
+ * Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/endian.h>
+
+#include "bnxt.h"
+#include "bnxt_hwrm.h"
+#include "hsi_struct_def.h"
+
+static int bnxt_hwrm_err_map(uint16_t err);
+static inline int _is_valid_ether_addr(uint8_t *);
+static inline void get_random_ether_addr(uint8_t *);
+static void bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
+ struct hwrm_port_phy_cfg_input *req);
+static void bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
+ struct hwrm_port_phy_cfg_input *req);
+static void bnxt_hwrm_set_eee(struct bnxt_softc *softc,
+ struct hwrm_port_phy_cfg_input *req);
+static int _hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
+static int hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
+static void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t);
+
+/* NVRam stuff has a five minute timeout */
+#define BNXT_NVM_TIMEO (5 * 60 * 1000)
+
+static int
+bnxt_hwrm_err_map(uint16_t err)
+{
+ int rc;
+
+ switch (err) {
+ case HWRM_ERR_CODE_SUCCESS:
+ return 0;
+ case HWRM_ERR_CODE_INVALID_PARAMS:
+ case HWRM_ERR_CODE_INVALID_FLAGS:
+ case HWRM_ERR_CODE_INVALID_ENABLES:
+ return EINVAL;
+ case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
+ return EACCES;
+ case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
+ return ENOMEM;
+ case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
+ return ENOSYS;
+ case HWRM_ERR_CODE_FAIL:
+ return EIO;
+ case HWRM_ERR_CODE_HWRM_ERROR:
+ case HWRM_ERR_CODE_UNKNOWN_ERR:
+ default:
+ return EDOOFUS;
+ }
+
+ return rc;
+}
+
+int
+bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc)
+{
+ int rc;
+
+ rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp,
+ BUS_DMA_NOWAIT);
+ return rc;
+}
+
+void
+bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc)
+{
+ if (softc->hwrm_cmd_resp.idi_vaddr)
+ iflib_dma_free(&softc->hwrm_cmd_resp);
+ softc->hwrm_cmd_resp.idi_vaddr = NULL;
+ return;
+}
+
+static void
+bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
+ uint16_t req_type)
+{
+ struct input *req = request;
+
+ req->req_type = htole16(req_type);
+ req->cmpl_ring = 0xffff;
+ req->target_id = 0xffff;
+ req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
+}
+
+static int
+_hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
+{
+ struct input *req = msg;
+ struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ uint32_t *data = msg;
+ int i;
+ uint16_t cp_ring_id;
+ uint8_t *valid;
+ uint16_t err;
+
+ /* TODO: DMASYNC in here. */
+ req->seq_id = htole16(softc->hwrm_cmd_seq++);
+ memset(resp, 0, PAGE_SIZE);
+ cp_ring_id = le16toh(req->cmpl_ring);
+
+ /* Write request msg to hwrm channel */
+ for (i = 0; i < msg_len; i += 4) {
+ bus_space_write_4(softc->hwrm_bar.tag,
+ softc->hwrm_bar.handle,
+ i, *data);
+ data++;
+ }
+
+ /* Clear to the end of the request buffer */
+ for (i = msg_len; i < HWRM_MAX_REQ_LEN; i += 4)
+ bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
+ i, 0);
+
+ /* Ring channel doorbell */
+ bus_space_write_4(softc->hwrm_bar.tag,
+ softc->hwrm_bar.handle,
+ 0x100, htole32(1));
+
+ /* Check if response len is updated */
+ for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
+ if (resp->resp_len && resp->resp_len <= 4096)
+ break;
+ DELAY(1000);
+ }
+ if (i >= softc->hwrm_cmd_timeo) {
+ device_printf(softc->dev,
+ "Timeout sending %s: (timeout: %u) seq: %d\n",
+ GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
+ le16toh(req->seq_id));
+ return ETIMEDOUT;
+ }
+ /* Last byte of resp contains the valid key */
+ valid = (uint8_t *)resp + resp->resp_len - 1;
+ for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
+ if (*valid == HWRM_RESP_VALID_KEY)
+ break;
+ DELAY(1000);
+ }
+ if (i >= softc->hwrm_cmd_timeo) {
+ device_printf(softc->dev, "Timeout sending %s: "
+ "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
+ GET_HWRM_REQ_TYPE(req->req_type),
+ softc->hwrm_cmd_timeo, le16toh(req->req_type),
+ le16toh(req->seq_id), msg_len,
+ *valid);
+ return ETIMEDOUT;
+ }
+
+ err = le16toh(resp->error_code);
+ if (err) {
+ /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
+ if (err != HWRM_ERR_CODE_FAIL) {
+ device_printf(softc->dev,
+ "%s command returned %s error.\n",
+ GET_HWRM_REQ_TYPE(req->req_type),
+ GET_HWRM_ERROR_CODE(err));
+ }
+ return bnxt_hwrm_err_map(err);
+ }
+
+ return 0;
+}
+
+static int
+hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
+{
+ int rc;
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, msg, msg_len);
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
+{
+ struct hwrm_queue_qportcfg_input req = {0};
+ struct hwrm_queue_qportcfg_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+
+ int rc = 0;
+ uint8_t *qptr;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto qportcfg_exit;
+
+ if (!resp->max_configurable_queues) {
+ rc = -EINVAL;
+ goto qportcfg_exit;
+ }
+ softc->max_tc = resp->max_configurable_queues;
+ if (softc->max_tc > BNXT_MAX_QUEUE)
+ softc->max_tc = BNXT_MAX_QUEUE;
+
+ qptr = &resp->queue_id0;
+ for (int i = 0; i < softc->max_tc; i++) {
+ softc->q_info[i].id = *qptr++;
+ softc->q_info[i].profile = *qptr++;
+ }
+
+qportcfg_exit:
+ BNXT_HWRM_UNLOCK(softc);
+ return (rc);
+}
+
+
+int
+bnxt_hwrm_ver_get(struct bnxt_softc *softc)
+{
+ struct hwrm_ver_get_input req = {0};
+ struct hwrm_ver_get_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc;
+ const char nastr[] = "<not installed>";
+ const char naver[] = "<N/A>";
+
+ softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
+ softc->hwrm_cmd_timeo = 1000;
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
+
+ req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
+ req.hwrm_intf_min = HWRM_VERSION_MINOR;
+ req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto fail;
+
+ snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
+ resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd);
+ softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj;
+ softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min;
+ softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd;
+ snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
+ resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld);
+ strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
+ BNXT_VERSTR_SIZE);
+ strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
+ BNXT_NAME_SIZE);
+
+ if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 &&
+ resp->mgmt_fw_bld == 0) {
+ strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
+ strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
+ }
+ else {
+ snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
+ "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min,
+ resp->mgmt_fw_bld);
+ strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
+ BNXT_NAME_SIZE);
+ }
+ if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 &&
+ resp->netctrl_fw_bld == 0) {
+ strlcpy(softc->ver_info->netctrl_fw_ver, naver,
+ BNXT_VERSTR_SIZE);
+ strlcpy(softc->ver_info->netctrl_fw_name, nastr,
+ BNXT_NAME_SIZE);
+ }
+ else {
+ snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
+ "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min,
+ resp->netctrl_fw_bld);
+ strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
+ BNXT_NAME_SIZE);
+ }
+ if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 &&
+ resp->roce_fw_bld == 0) {
+ strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
+ strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
+ }
+ else {
+ snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
+ "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min,
+ resp->roce_fw_bld);
+ strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
+ BNXT_NAME_SIZE);
+ }
+ softc->ver_info->chip_num = le16toh(resp->chip_num);
+ softc->ver_info->chip_rev = resp->chip_rev;
+ softc->ver_info->chip_metal = resp->chip_metal;
+ softc->ver_info->chip_bond_id = resp->chip_bond_id;
+ softc->ver_info->chip_type = resp->chip_platform_type;
+
+ if (resp->max_req_win_len)
+ softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
+ if (resp->def_req_timeout)
+ softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
+
+fail:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
+{
+ struct hwrm_func_drv_rgtr_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
+
+ req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
+ HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
+ req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
+
+ req.ver_maj = __FreeBSD_version / 100000;
+ req.ver_min = (__FreeBSD_version / 1000) % 100;
+ req.ver_upd = (__FreeBSD_version / 100) % 10;
+
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
+
+int
+bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
+{
+ struct hwrm_func_drv_unrgtr_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
+ if (shutdown == true)
+ req.flags |=
+ HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
+
+static inline int
+_is_valid_ether_addr(uint8_t *addr)
+{
+ char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
+
+ if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
+ return (FALSE);
+
+ return (TRUE);
+}
+
+static inline void
+get_random_ether_addr(uint8_t *addr)
+{
+ uint8_t temp[ETHER_ADDR_LEN];
+
+ arc4rand(&temp, sizeof(temp), 0);
+ temp[0] &= 0xFE;
+ temp[0] |= 0x02;
+ bcopy(temp, addr, sizeof(temp));
+}
+
+int
+bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
+{
+ int rc = 0;
+ struct hwrm_func_qcaps_input req = {0};
+ struct hwrm_func_qcaps_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ struct bnxt_func_info *func = &softc->func;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
+ req.fid = htole16(0xffff);
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto fail;
+
+ func->fw_fid = le16toh(resp->fid);
+ memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
+ func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
+ func->max_cp_rings = le16toh(resp->max_cmpl_rings);
+ func->max_tx_rings = le16toh(resp->max_tx_rings);
+ func->max_rx_rings = le16toh(resp->max_rx_rings);
+ func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
+ if (!func->max_hw_ring_grps)
+ func->max_hw_ring_grps = func->max_tx_rings;
+ func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
+ func->max_vnics = le16toh(resp->max_vnics);
+ func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
+ if (BNXT_PF(softc)) {
+ struct bnxt_pf_info *pf = &softc->pf;
+
+ pf->port_id = le16toh(resp->port_id);
+ pf->first_vf_id = le16toh(resp->first_vf_id);
+ pf->max_vfs = le16toh(resp->max_vfs);
+ pf->max_encap_records = le32toh(resp->max_encap_records);
+ pf->max_decap_records = le32toh(resp->max_decap_records);
+ pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
+ pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
+ pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
+ pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
+ }
+ if (!_is_valid_ether_addr(func->mac_addr)) {
+ device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
+ get_random_ether_addr(func->mac_addr);
+ }
+
+fail:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_func_reset(struct bnxt_softc *softc)
+{
+ struct hwrm_func_reset_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
+ req.enables = 0;
+
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
+static void
+bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
+ struct hwrm_port_phy_cfg_input *req)
+{
+ uint8_t autoneg = softc->link_info.autoneg;
+ uint16_t fw_link_speed = softc->link_info.req_link_speed;
+
+ if (autoneg & BNXT_AUTONEG_SPEED) {
+ req->auto_mode |=
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
+
+ req->enables |=
+ htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
+ req->flags |=
+ htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
+ } else {
+ req->force_link_speed = htole16(fw_link_speed);
+ req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
+ }
+
+ /* tell chimp that the setting takes effect immediately */
+ req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
+}
+
+
+static void
+bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
+ struct hwrm_port_phy_cfg_input *req)
+{
+ if (softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) {
+ req->auto_pause =
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
+ if (softc->link_info.req_flow_ctrl &
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
+ req->auto_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
+ if (softc->link_info.req_flow_ctrl &
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
+ req->auto_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
+ req->enables |=
+ htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
+ } else {
+ if (softc->link_info.req_flow_ctrl &
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
+ req->force_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
+ if (softc->link_info.req_flow_ctrl &
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
+ req->force_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
+ req->enables |=
+ htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
+ req->auto_pause = req->force_pause;
+ req->enables |= htole32(
+ HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
+ }
+}
+
+
+/* JFV this needs interface connection */
+static void
+bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
+{
+ /* struct ethtool_eee *eee = &softc->eee; */
+ bool eee_enabled = false;
+
+ if (eee_enabled) {
+#if 0
+ uint16_t eee_speeds;
+ uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
+
+ if (eee->tx_lpi_enabled)
+ flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
+
+ req->flags |= htole32(flags);
+ eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
+ req->eee_link_speed_mask = htole16(eee_speeds);
+ req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
+#endif
+ } else {
+ req->flags |=
+ htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
+ }
+}
+
+
+int
+bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
+ bool set_eee)
+{
+ struct hwrm_port_phy_cfg_input req = {0};
+
+ if (softc->flags & BNXT_FLAG_NPAR)
+ return ENOTSUP;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
+ if (set_pause)
+ bnxt_hwrm_set_pause_common(softc, &req);
+
+ bnxt_hwrm_set_link_common(softc, &req);
+ if (set_eee)
+ bnxt_hwrm_set_eee(softc, &req);
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
+
+int
+bnxt_hwrm_set_pause(struct bnxt_softc *softc)
+{
+ struct hwrm_port_phy_cfg_input req = {0};
+ int rc;
+
+ if (softc->flags & BNXT_FLAG_NPAR)
+ return ENOTSUP;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
+ bnxt_hwrm_set_pause_common(softc, &req);
+
+ if (softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)
+ bnxt_hwrm_set_link_common(softc, &req);
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (!rc && !(softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)) {
+ /* since changing of pause setting doesn't trigger any link
+ * change event, the driver needs to update the current pause
+ * result upon successfully return of the phy_cfg command */
+ softc->link_info.pause =
+ softc->link_info.force_pause = softc->link_info.req_flow_ctrl;
+ softc->link_info.auto_pause = 0;
+ bnxt_report_link(softc);
+ }
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
+{
+ struct hwrm_vnic_cfg_input req = {0};
+ struct hwrm_vnic_cfg_output *resp;
+
+ resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
+
+ if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
+ req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
+ if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
+ req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
+ if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
+ req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
+ req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
+ HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE |
+ HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
+ req.vnic_id = htole16(vnic->id);
+ req.dflt_ring_grp = htole16(vnic->def_ring_grp);
+ req.rss_rule = htole16(vnic->rss_id);
+ req.cos_rule = htole16(vnic->cos_rule);
+ req.lb_rule = htole16(vnic->lb_rule);
+ req.mru = htole16(vnic->mru);
+
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
+int
+bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
+{
+ struct hwrm_vnic_alloc_input req = {0};
+ struct hwrm_vnic_alloc_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc;
+
+ if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
+ device_printf(softc->dev,
+ "Attempt to re-allocate vnic %04x\n", vnic->id);
+ return EDOOFUS;
+ }
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
+
+ if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
+ req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto fail;
+
+ vnic->id = le32toh(resp->vnic_id);
+
+fail:
+ BNXT_HWRM_UNLOCK(softc);
+ return (rc);
+}
+
+int
+bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
+{
+ struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
+ struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc;
+
+ if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
+ device_printf(softc->dev,
+ "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
+ return EDOOFUS;
+ }
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto fail;
+
+ *ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
+
+fail:
+ BNXT_HWRM_UNLOCK(softc);
+ return (rc);
+}
+
+int
+bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
+{
+ struct hwrm_ring_grp_alloc_input req = {0};
+ struct hwrm_ring_grp_alloc_output *resp;
+ int rc = 0;
+
+ if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
+ device_printf(softc->dev,
+ "Attempt to re-allocate ring group %04x\n", grp->grp_id);
+ return EDOOFUS;
+ }
+
+ resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
+ req.cr = htole16(grp->cp_ring_id);
+ req.rr = htole16(grp->rx_ring_id);
+ req.ar = htole16(grp->ag_ring_id);
+ req.sc = htole16(grp->stats_ctx);
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto fail;
+
+ grp->grp_id = le32toh(resp->ring_group_id);
+
+fail:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+/*
+ * Ring allocation message to the firmware
+ */
+int
+bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
+ struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
+ bool irq)
+{
+ struct hwrm_ring_alloc_input req = {0};
+ struct hwrm_ring_alloc_output *resp;
+ int rc;
+
+ if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
+ device_printf(softc->dev,
+ "Attempt to re-allocate ring %04x\n", ring->phys_id);
+ return EDOOFUS;
+ }
+
+ resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
+ req.enables = htole32(0);
+ req.fbo = htole32(0);
+
+ if (stat_ctx_id != HWRM_NA_SIGNATURE) {
+ req.enables |= htole32(
+ HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
+ req.stat_ctx_id = htole32(stat_ctx_id);
+ }
+ req.ring_type = type;
+ req.page_tbl_addr = htole64(ring->paddr);
+ req.length = htole32(ring->ring_size);
+ req.logical_id = htole16(ring->id);
+ req.cmpl_ring_id = htole16(cmpl_ring_id);
+ req.queue_id = htole16(softc->q_info[0].id);
+#if 0
+ /* MODE_POLL appears to crash the firmware */
+ if (irq)
+ req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
+ else
+ req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL;
+#else
+ req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
+#endif
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto fail;
+
+ ring->phys_id = le16toh(resp->ring_id);
+
+fail:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
+ uint64_t paddr)
+{
+ struct hwrm_stat_ctx_alloc_input req = {0};
+ struct hwrm_stat_ctx_alloc_output *resp;
+ int rc = 0;
+
+ if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
+ device_printf(softc->dev,
+ "Attempt to re-allocate stats ctx %08x\n",
+ cpr->stats_ctx_id);
+ return EDOOFUS;
+ }
+
+ resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
+
+ req.update_period_ms = htole32(1000);
+ req.stats_dma_addr = htole64(paddr);
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto fail;
+
+ cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
+
+fail:
+ BNXT_HWRM_UNLOCK(softc);
+
+ return rc;
+}
+
+int
+bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
+ struct bnxt_vnic_info *vnic)
+{
+ struct hwrm_cfa_l2_set_rx_mask_input req = {0};
+ struct bnxt_vlan_tag *tag;
+ uint32_t *tags;
+ uint32_t num_vlan_tags = 0;;
+ uint32_t i;
+ uint32_t mask = vnic->rx_mask;
+ int rc;
+
+ SLIST_FOREACH(tag, &vnic->vlan_tags, next)
+ num_vlan_tags++;
+
+ if (num_vlan_tags) {
+ if (!(mask &
+ HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN)) {
+ if (!vnic->vlan_only)
+ mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN;
+ else
+ mask |=
+ HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY;
+ }
+ if (vnic->vlan_tag_list.idi_vaddr) {
+ iflib_dma_free(&vnic->vlan_tag_list);
+ vnic->vlan_tag_list.idi_vaddr = NULL;
+ }
+ rc = iflib_dma_alloc(softc->ctx, 4 * num_vlan_tags,
+ &vnic->vlan_tag_list, BUS_DMA_NOWAIT);
+ if (rc)
+ return rc;
+ tags = (uint32_t *)vnic->vlan_tag_list.idi_vaddr;
+
+ i = 0;
+ SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
+ tags[i] = htole32((tag->tpid << 16) | tag->tag);
+ i++;
+ }
+ }
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
+
+ req.vnic_id = htole32(vnic->id);
+ req.mask = htole32(mask);
+ req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
+ req.num_mc_entries = htole32(vnic->mc_list_count);
+ req.vlan_tag_tbl_addr = htole64(vnic->vlan_tag_list.idi_paddr);
+ req.num_vlan_tags = htole32(num_vlan_tags);
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
+
+int
+bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
+{
+ struct hwrm_cfa_l2_filter_alloc_input req = {0};
+ struct hwrm_cfa_l2_filter_alloc_output *resp;
+ uint32_t enables = 0;
+ int rc = 0;
+
+ if (vnic->filter_id != -1) {
+ device_printf(softc->dev,
+ "Attempt to re-allocate l2 ctx filter\n");
+ return EDOOFUS;
+ }
+
+ resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
+
+ req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
+ enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
+ | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
+ | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
+ req.enables = htole32(enables);
+ req.dst_id = htole16(vnic->id);
+ memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
+ ETHER_ADDR_LEN);
+ memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto fail;
+
+ vnic->filter_id = le64toh(resp->l2_filter_id);
+ vnic->flow_id = le64toh(resp->flow_id);
+
+fail:
+ BNXT_HWRM_UNLOCK(softc);
+ return (rc);
+}
+
+int
+bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
+ uint32_t hash_type)
+{
+ struct hwrm_vnic_rss_cfg_input req = {0};
+ struct hwrm_vnic_rss_cfg_output *resp;
+
+ resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
+
+ req.hash_type = htole32(hash_type);
+ req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
+ req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
+ req.rss_ctx_idx = htole16(vnic->rss_id);
+
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
+int
+bnxt_hwrm_func_cfg(struct bnxt_softc *softc)
+{
+ struct hwrm_func_cfg_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
+
+ req.fid = 0xffff;
+ req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
+
+ req.async_event_cr = softc->def_cp_ring.ring.phys_id;
+
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
+int
+bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
+ uint32_t flags)
+{
+ struct hwrm_vnic_tpa_cfg_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
+
+ req.flags = htole32(flags);
+ req.vnic_id = htole16(vnic->id);
+ req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
+ HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
+ /* HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_TIMER | */
+ HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
+ /* TODO: Calculate this based on ring size? */
+ req.max_agg_segs = htole16(3);
+ /* Base this in the allocated TPA start size... */
+ req.max_aggs = htole16(2);
+ /*
+ * TODO: max_agg_timer?
+ * req.mag_agg_timer = htole32(XXX);
+ */
+ req.min_agg_len = htole32(0);
+
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
+int
+bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
+ uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
+ uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
+ uint32_t *fw_ver)
+{
+ struct hwrm_nvm_find_dir_entry_input req = {0};
+ struct hwrm_nvm_find_dir_entry_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc = 0;
+ uint32_t old_timeo;
+
+ MPASS(ordinal);
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
+ if (use_index) {
+ req.enables = htole32(
+ HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
+ req.dir_idx = htole16(*index);
+ }
+ req.dir_type = htole16(type);
+ req.dir_ordinal = htole16(*ordinal);
+ req.dir_ext = htole16(ext);
+ req.opt_ordinal = search_opt;
+
+ BNXT_HWRM_LOCK(softc);
+ old_timeo = softc->hwrm_cmd_timeo;
+ softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ softc->hwrm_cmd_timeo = old_timeo;
+ if (rc)
+ goto exit;
+
+ if (item_length)
+ *item_length = le32toh(resp->dir_item_length);
+ if (data_length)
+ *data_length = le32toh(resp->dir_data_length);
+ if (fw_ver)
+ *fw_ver = le32toh(resp->fw_ver);
+ *ordinal = le16toh(resp->dir_ordinal);
+ if (index)
+ *index = le16toh(resp->dir_idx);
+
+exit:
+ BNXT_HWRM_UNLOCK(softc);
+ return (rc);
+}
+
+int
+bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
+ uint32_t length, struct iflib_dma_info *data)
+{
+ struct hwrm_nvm_read_input req = {0};
+ int rc;
+ uint32_t old_timeo;
+
+ if (length > data->idi_size) {
+ rc = EINVAL;
+ goto exit;
+ }
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
+ req.host_dest_addr = htole64(data->idi_paddr);
+ req.dir_idx = htole16(index);
+ req.offset = htole32(offset);
+ req.len = htole32(length);
+ BNXT_HWRM_LOCK(softc);
+ old_timeo = softc->hwrm_cmd_timeo;
+ softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ softc->hwrm_cmd_timeo = old_timeo;
+ BNXT_HWRM_UNLOCK(softc);
+ if (rc)
+ goto exit;
+ bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
+
+ goto exit;
+
+exit:
+ return rc;
+}
+
+int
+bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
+ void *data, bool cpyin, uint32_t length)
+{
+ struct hwrm_nvm_modify_input req = {0};
+ struct iflib_dma_info dma_data;
+ int rc;
+ uint32_t old_timeo;
+
+ if (length == 0 || !data)
+ return EINVAL;
+ rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
+ BUS_DMA_NOWAIT);
+ if (rc)
+ return ENOMEM;
+ if (cpyin) {
+ rc = copyin(data, dma_data.idi_vaddr, length);
+ if (rc)
+ goto exit;
+ }
+ else
+ memcpy(dma_data.idi_vaddr, data, length);
+ bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
+ req.host_src_addr = htole64(dma_data.idi_paddr);
+ req.dir_idx = htole16(index);
+ req.offset = htole32(offset);
+ req.len = htole32(length);
+ BNXT_HWRM_LOCK(softc);
+ old_timeo = softc->hwrm_cmd_timeo;
+ softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ softc->hwrm_cmd_timeo = old_timeo;
+ BNXT_HWRM_UNLOCK(softc);
+
+exit:
+ iflib_dma_free(&dma_data);
+ return rc;
+}
+
+int
+bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
+ uint8_t *selfreset)
+{
+ struct hwrm_fw_reset_input req = {0};
+ struct hwrm_fw_reset_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc;
+
+ MPASS(selfreset);
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
+ req.embedded_proc_type = processor;
+ req.selfrst_status = *selfreset;
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto exit;
+ *selfreset = resp->selfrst_status;
+
+exit:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
+{
+ struct hwrm_fw_qstatus_input req = {0};
+ struct hwrm_fw_qstatus_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc;
+
+ MPASS(selfreset);
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
+ req.embedded_proc_type = type;
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto exit;
+ *selfreset = resp->selfrst_status;
+
+exit:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
+ uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
+ uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
+ uint16_t *index)
+{
+ struct hwrm_nvm_write_input req = {0};
+ struct hwrm_nvm_write_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ struct iflib_dma_info dma_data;
+ int rc;
+ uint32_t old_timeo;
+
+ if (data_length) {
+ rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
+ BUS_DMA_NOWAIT);
+ if (rc)
+ return ENOMEM;
+ if (cpyin) {
+ rc = copyin(data, dma_data.idi_vaddr, data_length);
+ if (rc)
+ goto early_exit;
+ }
+ else
+ memcpy(dma_data.idi_vaddr, data, data_length);
+ bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ }
+ else
+ dma_data.idi_paddr = 0;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
+
+ req.host_src_addr = htole64(dma_data.idi_paddr);
+ req.dir_type = htole16(type);
+ req.dir_ordinal = htole16(ordinal);
+ req.dir_ext = htole16(ext);
+ req.dir_attr = htole16(attr);
+ req.dir_data_length = htole32(data_length);
+ req.option = htole16(option);
+ if (keep) {
+ req.flags =
+ htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
+ }
+ if (item_length)
+ req.dir_item_length = htole32(*item_length);
+
+ BNXT_HWRM_LOCK(softc);
+ old_timeo = softc->hwrm_cmd_timeo;
+ softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ softc->hwrm_cmd_timeo = old_timeo;
+ if (rc)
+ goto exit;
+ if (item_length)
+ *item_length = le32toh(resp->dir_item_length);
+ if (index)
+ *index = le16toh(resp->dir_idx);
+
+exit:
+ BNXT_HWRM_UNLOCK(softc);
+early_exit:
+ if (data_length)
+ iflib_dma_free(&dma_data);
+ return rc;
+}
+
+int
+bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
+{
+ struct hwrm_nvm_erase_dir_entry_input req = {0};
+ uint32_t old_timeo;
+ int rc;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
+ req.dir_idx = htole16(index);
+ BNXT_HWRM_LOCK(softc);
+ old_timeo = softc->hwrm_cmd_timeo;
+ softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ softc->hwrm_cmd_timeo = old_timeo;
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
+ uint32_t *entry_length)
+{
+ struct hwrm_nvm_get_dir_info_input req = {0};
+ struct hwrm_nvm_get_dir_info_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc;
+ uint32_t old_timeo;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
+
+ BNXT_HWRM_LOCK(softc);
+ old_timeo = softc->hwrm_cmd_timeo;
+ softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ softc->hwrm_cmd_timeo = old_timeo;
+ if (rc)
+ goto exit;
+
+ if (entries)
+ *entries = le32toh(resp->entries);
+ if (entry_length)
+ *entry_length = le32toh(resp->entry_length);
+
+exit:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
+ uint32_t *entry_length, struct iflib_dma_info *dma_data)
+{
+ struct hwrm_nvm_get_dir_entries_input req = {0};
+ uint32_t ent;
+ uint32_t ent_len;
+ int rc;
+ uint32_t old_timeo;
+
+ if (!entries)
+ entries = &ent;
+ if (!entry_length)
+ entry_length = &ent_len;
+
+ rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
+ if (rc)
+ goto exit;
+ if (*entries * *entry_length > dma_data->idi_size) {
+ rc = EINVAL;
+ goto exit;
+ }
+
+ /*
+ * TODO: There's a race condition here that could blow up DMA memory...
+ * we need to allocate the max size, not the currently in use
+ * size. The command should totally have a max size here.
+ */
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
+ req.host_dest_addr = htole64(dma_data->idi_paddr);
+ BNXT_HWRM_LOCK(softc);
+ old_timeo = softc->hwrm_cmd_timeo;
+ softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ softc->hwrm_cmd_timeo = old_timeo;
+ BNXT_HWRM_UNLOCK(softc);
+ if (rc)
+ goto exit;
+ bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
+ BUS_DMASYNC_POSTWRITE);
+
+exit:
+ return rc;
+}
+
+int
+bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
+ uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
+ uint32_t *reserved_size, uint32_t *available_size)
+{
+ struct hwrm_nvm_get_dev_info_input req = {0};
+ struct hwrm_nvm_get_dev_info_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc;
+ uint32_t old_timeo;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
+
+ BNXT_HWRM_LOCK(softc);
+ old_timeo = softc->hwrm_cmd_timeo;
+ softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ softc->hwrm_cmd_timeo = old_timeo;
+ if (rc)
+ goto exit;
+
+ if (mfg_id)
+ *mfg_id = le16toh(resp->manufacturer_id);
+ if (device_id)
+ *device_id = le16toh(resp->device_id);
+ if (sector_size)
+ *sector_size = le32toh(resp->sector_size);
+ if (nvram_size)
+ *nvram_size = le32toh(resp->nvram_size);
+ if (reserved_size)
+ *reserved_size = le32toh(resp->reserved_size);
+ if (available_size)
+ *available_size = le32toh(resp->available_size);
+
+exit:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
+ uint32_t install_type, uint64_t *installed_items, uint8_t *result,
+ uint8_t *problem_item, uint8_t *reset_required)
+{
+ struct hwrm_nvm_install_update_input req = {0};
+ struct hwrm_nvm_install_update_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc;
+ uint32_t old_timeo;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
+ req.install_type = htole32(install_type);
+
+ BNXT_HWRM_LOCK(softc);
+ old_timeo = softc->hwrm_cmd_timeo;
+ softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ softc->hwrm_cmd_timeo = old_timeo;
+ if (rc)
+ goto exit;
+
+ if (installed_items)
+ *installed_items = le32toh(resp->installed_items);
+ if (result)
+ *result = resp->result;
+ if (problem_item)
+ *problem_item = resp->problem_item;
+ if (reset_required)
+ *reset_required = resp->reset_required;
+
+exit:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
+ uint16_t ordinal, uint16_t ext)
+{
+ struct hwrm_nvm_verify_update_input req = {0};
+ uint32_t old_timeo;
+ int rc;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
+
+ req.dir_type = htole16(type);
+ req.dir_ordinal = htole16(ordinal);
+ req.dir_ext = htole16(ext);
+
+ BNXT_HWRM_LOCK(softc);
+ old_timeo = softc->hwrm_cmd_timeo;
+ softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ softc->hwrm_cmd_timeo = old_timeo;
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
+ uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
+ uint16_t *millisecond, uint16_t *zone)
+{
+ struct hwrm_fw_get_time_input req = {0};
+ struct hwrm_fw_get_time_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
+
+ BNXT_HWRM_LOCK(softc);
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto exit;
+
+ if (year)
+ *year = le16toh(resp->year);
+ if (month)
+ *month = resp->month;
+ if (day)
+ *day = resp->day;
+ if (hour)
+ *hour = resp->hour;
+ if (minute)
+ *minute = resp->minute;
+ if (second)
+ *second = resp->second;
+ if (millisecond)
+ *millisecond = le16toh(resp->millisecond);
+ if (zone)
+ *zone = le16toh(resp->zone);
+
+exit:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
+
+int
+bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
+ uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
+ uint16_t millisecond, uint16_t zone)
+{
+ struct hwrm_fw_set_time_input req = {0};
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
+
+ req.year = htole16(year);
+ req.month = month;
+ req.day = day;
+ req.hour = hour;
+ req.minute = minute;
+ req.second = second;
+ req.millisecond = htole16(millisecond);
+ req.zone = htole16(zone);
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
+int
+bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
+{
+ struct bnxt_link_info *link_info = &softc->link_info;
+ struct hwrm_port_phy_qcfg_input req = {0};
+ struct hwrm_port_phy_qcfg_output *resp =
+ (void *)softc->hwrm_cmd_resp.idi_vaddr;
+ int rc = 0;
+
+ BNXT_HWRM_LOCK(softc);
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
+
+ rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (rc)
+ goto exit;
+
+ link_info->phy_link_status = resp->link;
+ link_info->duplex = resp->duplex;
+ link_info->pause = resp->pause;
+ link_info->auto_mode = resp->auto_mode;
+ link_info->auto_pause = resp->auto_pause;
+ link_info->force_pause = resp->force_pause;
+ link_info->duplex_setting = resp->duplex;
+ if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
+ link_info->link_speed = le16toh(resp->link_speed);
+ else
+ link_info->link_speed = 0;
+ link_info->force_link_speed = le16toh(resp->force_link_speed);
+ link_info->auto_link_speed = le16toh(resp->auto_link_speed);
+ link_info->support_speeds = le16toh(resp->support_speeds);
+ link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
+ link_info->preemphasis = le32toh(resp->preemphasis);
+ link_info->phy_ver[0] = resp->phy_maj;
+ link_info->phy_ver[1] = resp->phy_min;
+ link_info->phy_ver[2] = resp->phy_bld;
+ snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
+ "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
+ link_info->phy_ver[2]);
+ strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
+ BNXT_NAME_SIZE);
+ strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
+ BNXT_NAME_SIZE);
+ link_info->media_type = resp->media_type;
+ link_info->phy_type = resp->phy_type;
+ link_info->transceiver = resp->xcvr_pkg_type;
+ link_info->phy_addr = resp->eee_config_phy_addr &
+ HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
+
+exit:
+ BNXT_HWRM_UNLOCK(softc);
+ return rc;
+}
diff --git a/sys/dev/bnxt/bnxt_hwrm.h b/sys/dev/bnxt/bnxt_hwrm.h
new file mode 100644
index 000000000000..21fc2272c855
--- /dev/null
+++ b/sys/dev/bnxt/bnxt_hwrm.h
@@ -0,0 +1,102 @@
+/*-
+ * Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 _BNXT_HWRM_H
+#define _BNXT_HWRM_H
+
+/* HWRM Function Prototypes */
+int bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc);
+void bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc);
+int bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
+ struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
+ bool irq);
+int bnxt_hwrm_ver_get(struct bnxt_softc *softc);
+int bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc);
+int bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc);
+int bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown);
+int bnxt_hwrm_func_qcaps(struct bnxt_softc *softc);
+int bnxt_hwrm_func_reset(struct bnxt_softc *softc);
+int bnxt_hwrm_set_link_setting(struct bnxt_softc *, bool set_pause,
+ bool set_eee);
+int bnxt_hwrm_set_pause(struct bnxt_softc *softc);
+int bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id);
+int bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic);
+int bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
+ uint64_t paddr);
+int bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc,
+ struct bnxt_grp_info *grp);
+int bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic);
+int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
+ struct bnxt_vnic_info *vnic);
+int bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic);
+int bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
+ uint32_t hash_type);
+int bnxt_hwrm_func_cfg(struct bnxt_softc *softc);
+int bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc,
+ struct bnxt_vnic_info *vnic, uint32_t flags);
+int bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
+ uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
+ uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
+ uint32_t *fw_ver);
+int bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index,
+ uint32_t offset, uint32_t length, struct iflib_dma_info *data);
+int bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index,
+ uint32_t offset, void *data, bool cpyin, uint32_t length);
+int bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
+ uint8_t *selfreset);
+int bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type,
+ uint8_t *selfreset);
+int bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
+ uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
+ uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
+ uint16_t *index);
+int bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index);
+int bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
+ uint32_t *entry_length);
+int bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc,
+ uint32_t *entries, uint32_t *entry_length, struct iflib_dma_info *dma_data);
+int bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
+ uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
+ uint32_t *reserved_size, uint32_t *available_size);
+int bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
+ uint32_t install_type, uint64_t *installed_items, uint8_t *result,
+ uint8_t *problem_item, uint8_t *reset_required);
+int bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
+ uint16_t ordinal, uint16_t ext);
+int bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year,
+ uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute,
+ uint8_t *second, uint16_t *millisecond, uint16_t *zone);
+int bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year,
+ uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
+ uint16_t millisecond, uint16_t zone);
+int bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc);
+
+#endif
diff --git a/sys/dev/bnxt/bnxt_ioctl.h b/sys/dev/bnxt/bnxt_ioctl.h
new file mode 100644
index 000000000000..af6c719b914d
--- /dev/null
+++ b/sys/dev/bnxt/bnxt_ioctl.h
@@ -0,0 +1,192 @@
+/*-
+ * Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 _BNXT_IOCTL_H
+#define _BNXT_IOCTL_H
+
+enum bnxt_ioctl_type {
+ BNXT_HWRM_NVM_FIND_DIR_ENTRY,
+ BNXT_HWRM_NVM_READ,
+ BNXT_HWRM_FW_RESET,
+ BNXT_HWRM_FW_QSTATUS,
+ BNXT_HWRM_NVM_WRITE,
+ BNXT_HWRM_NVM_ERASE_DIR_ENTRY,
+ BNXT_HWRM_NVM_GET_DIR_INFO,
+ BNXT_HWRM_NVM_GET_DIR_ENTRIES,
+ BNXT_HWRM_NVM_MODIFY,
+ BNXT_HWRM_NVM_VERIFY_UPDATE,
+ BNXT_HWRM_NVM_INSTALL_UPDATE,
+ BNXT_HWRM_FW_GET_TIME,
+ BNXT_HWRM_FW_SET_TIME,
+};
+
+struct bnxt_ioctl_header {
+ enum bnxt_ioctl_type type;
+ int rc;
+};
+
+struct bnxt_ioctl_hwrm_nvm_find_dir_entry {
+ struct bnxt_ioctl_header hdr;
+ uint32_t data_length;
+ uint32_t fw_ver;
+ uint32_t item_length;
+ uint16_t ext;
+ uint16_t index;
+ uint16_t ordinal;
+ uint16_t type;
+ uint8_t search_opt;
+ bool use_index;
+};
+
+struct bnxt_ioctl_hwrm_nvm_read {
+ struct bnxt_ioctl_header hdr;
+ uint8_t *data;
+ uint32_t length;
+ uint32_t offset;
+ uint16_t index;
+};
+
+struct bnxt_ioctl_hwrm_fw_reset {
+ struct bnxt_ioctl_header hdr;
+ uint8_t processor;
+ uint8_t selfreset;
+};
+
+struct bnxt_ioctl_hwrm_fw_qstatus {
+ struct bnxt_ioctl_header hdr;
+ uint8_t processor;
+ uint8_t selfreset;
+};
+
+struct bnxt_ioctl_hwrm_nvm_write {
+ struct bnxt_ioctl_header hdr;
+ uint8_t *data;
+ uint32_t data_length;
+ uint32_t item_length;
+ uint16_t attr;
+ uint16_t ext;
+ uint16_t index;
+ uint16_t option;
+ uint16_t ordinal;
+ uint16_t type;
+ bool keep;
+};
+
+struct bnxt_ioctl_hwrm_nvm_erase_dir_entry {
+ struct bnxt_ioctl_header hdr;
+ enum bnxt_ioctl_type type;
+ int rc;
+ uint16_t index;
+};
+
+struct bnxt_ioctl_hwrm_nvm_get_dir_info {
+ struct bnxt_ioctl_header hdr;
+ uint32_t entries;
+ uint32_t entry_length;
+};
+
+struct bnxt_ioctl_hwrm_nvm_get_dir_entries {
+ struct bnxt_ioctl_header hdr;
+ uint8_t *data;
+ size_t max_size;
+ uint32_t entries;
+ uint32_t entry_length;
+};
+
+struct bnxt_ioctl_hwrm_nvm_install_update {
+ struct bnxt_ioctl_header hdr;
+ uint64_t installed_items;
+ uint32_t install_type;
+ uint8_t problem_item;
+ uint8_t reset_required;
+ uint8_t result;
+};
+
+struct bnxt_ioctl_hwrm_nvm_verify_update {
+ struct bnxt_ioctl_header hdr;
+ uint16_t ext;
+ uint16_t ordinal;
+ uint16_t type;
+};
+
+struct bnxt_ioctl_hwrm_nvm_modify {
+ struct bnxt_ioctl_header hdr;
+ uint8_t *data;
+ uint32_t length;
+ uint32_t offset;
+ uint16_t index;
+};
+
+struct bnxt_ioctl_hwrm_fw_get_time {
+ struct bnxt_ioctl_header hdr;
+ uint16_t millisecond;
+ uint16_t year;
+ uint16_t zone;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t month;
+ uint8_t second;
+};
+
+struct bnxt_ioctl_hwrm_fw_set_time {
+ struct bnxt_ioctl_header hdr;
+ uint16_t millisecond;
+ uint16_t year;
+ uint16_t zone;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t month;
+ uint8_t second;
+};
+
+/* IOCTL interface */
+struct bnxt_ioctl_data {
+ union {
+ struct bnxt_ioctl_header hdr;
+ struct bnxt_ioctl_hwrm_nvm_find_dir_entry find;
+ struct bnxt_ioctl_hwrm_nvm_read read;
+ struct bnxt_ioctl_hwrm_fw_reset reset;
+ struct bnxt_ioctl_hwrm_fw_qstatus status;
+ struct bnxt_ioctl_hwrm_nvm_write write;
+ struct bnxt_ioctl_hwrm_nvm_erase_dir_entry erase;
+ struct bnxt_ioctl_hwrm_nvm_get_dir_info dir_info;
+ struct bnxt_ioctl_hwrm_nvm_get_dir_entries dir_entries;
+ struct bnxt_ioctl_hwrm_nvm_install_update install;
+ struct bnxt_ioctl_hwrm_nvm_verify_update verify;
+ struct bnxt_ioctl_hwrm_nvm_modify modify;
+ struct bnxt_ioctl_hwrm_fw_get_time get_time;
+ struct bnxt_ioctl_hwrm_fw_set_time set_time;
+ };
+};
+
+#endif
diff --git a/sys/dev/bnxt/bnxt_sysctl.c b/sys/dev/bnxt/bnxt_sysctl.c
new file mode 100644
index 000000000000..6f79b56f07ec
--- /dev/null
+++ b/sys/dev/bnxt/bnxt_sysctl.c
@@ -0,0 +1,618 @@
+/*-
+ * Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include "bnxt.h"
+#include "bnxt_hwrm.h"
+#include "bnxt_sysctl.h"
+
+static int bnxt_vlan_only_sysctl(SYSCTL_HANDLER_ARGS);
+/*
+ * We want to create:
+ * dev.bnxt.0.hwstats.txq0
+ * dev.bnxt.0.hwstats.txq0.txmbufs
+ * dev.bnxt.0.hwstats.rxq0
+ * dev.bnxt.0.hwstats.txq0.rxmbufs
+ * so the hwstats ctx list needs to be created in attach_post and populated
+ * during init.
+ *
+ * Then, it needs to be cleaned up in stop.
+ */
+
+int
+bnxt_init_sysctl_ctx(struct bnxt_softc *softc)
+{
+ struct sysctl_ctx_list *ctx;
+
+ sysctl_ctx_init(&softc->hw_stats);
+ ctx = device_get_sysctl_ctx(softc->dev);
+ softc->hw_stats_oid = SYSCTL_ADD_NODE(ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
+ "hwstats", CTLFLAG_RD, 0, "hardware statistics");
+ if (!softc->hw_stats_oid) {
+ sysctl_ctx_free(&softc->hw_stats);
+ return ENOMEM;
+ }
+
+ sysctl_ctx_init(&softc->ver_info->ver_ctx);
+ ctx = device_get_sysctl_ctx(softc->dev);
+ softc->ver_info->ver_oid = SYSCTL_ADD_NODE(ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
+ "ver", CTLFLAG_RD, 0, "hardware/firmware version information");
+ if (!softc->ver_info->ver_oid) {
+ sysctl_ctx_free(&softc->ver_info->ver_ctx);
+ return ENOMEM;
+ }
+
+ sysctl_ctx_init(&softc->nvm_info->nvm_ctx);
+ ctx = device_get_sysctl_ctx(softc->dev);
+ softc->nvm_info->nvm_oid = SYSCTL_ADD_NODE(ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
+ "nvram", CTLFLAG_RD, 0, "nvram information");
+ if (!softc->nvm_info->nvm_oid) {
+ sysctl_ctx_free(&softc->nvm_info->nvm_ctx);
+ return ENOMEM;
+ }
+
+ return 0;
+}
+
+int
+bnxt_free_sysctl_ctx(struct bnxt_softc *softc)
+{
+ int orc;
+ int rc = 0;
+
+ if (softc->hw_stats_oid != NULL) {
+ orc = sysctl_ctx_free(&softc->hw_stats);
+ if (orc)
+ rc = orc;
+ else
+ softc->hw_stats_oid = NULL;
+ }
+ if (softc->ver_info->ver_oid != NULL) {
+ orc = sysctl_ctx_free(&softc->ver_info->ver_ctx);
+ if (orc)
+ rc = orc;
+ else
+ softc->ver_info->ver_oid = NULL;
+ }
+ if (softc->nvm_info->nvm_oid != NULL) {
+ orc = sysctl_ctx_free(&softc->nvm_info->nvm_ctx);
+ if (orc)
+ rc = orc;
+ else
+ softc->nvm_info->nvm_oid = NULL;
+ }
+
+ return rc;
+}
+
+int
+bnxt_create_tx_sysctls(struct bnxt_softc *softc, int txr)
+{
+ struct sysctl_oid *oid;
+ struct ctx_hw_stats *tx_stats = (void *)softc->tx_stats.idi_vaddr;
+ char name[32];
+ char desc[64];
+
+ sprintf(name, "txq%d", txr);
+ sprintf(desc, "transmit queue %d", txr);
+ oid = SYSCTL_ADD_NODE(&softc->hw_stats,
+ SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name, CTLFLAG_RD, 0,
+ desc);
+ if (!oid)
+ return ENOMEM;
+
+
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "ucast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_ucast_pkts,
+ "unicast packets sent");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "mcast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_mcast_pkts,
+ "multicast packets sent");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "bcast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_bcast_pkts,
+ "broadcast packets sent");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "discard_pkts", CTLFLAG_RD,
+ &tx_stats[txr].tx_discard_pkts, "discarded transmit packets");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "drop_pkts", CTLFLAG_RD, &tx_stats[txr].tx_drop_pkts,
+ "dropped transmit packets");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "ucast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_ucast_bytes,
+ "unicast bytes sent");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "mcast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_mcast_bytes,
+ "multicast bytes sent");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "bcast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_bcast_bytes,
+ "broadcast bytes sent");
+
+ return 0;
+}
+
+int
+bnxt_create_rx_sysctls(struct bnxt_softc *softc, int rxr)
+{
+ struct sysctl_oid *oid;
+ struct ctx_hw_stats *rx_stats = (void *)softc->rx_stats.idi_vaddr;
+ char name[32];
+ char desc[64];
+
+ sprintf(name, "rxq%d", rxr);
+ sprintf(desc, "receive queue %d", rxr);
+ oid = SYSCTL_ADD_NODE(&softc->hw_stats,
+ SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name, CTLFLAG_RD, 0,
+ desc);
+ if (!oid)
+ return ENOMEM;
+
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "ucast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_ucast_pkts,
+ "unicast packets received");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "mcast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_mcast_pkts,
+ "multicast packets received");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "bcast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_bcast_pkts,
+ "broadcast packets received");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "discard_pkts", CTLFLAG_RD,
+ &rx_stats[rxr].rx_discard_pkts, "discarded receive packets");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "drop_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_drop_pkts,
+ "dropped receive packets");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "ucast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_ucast_bytes,
+ "unicast bytes received");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "mcast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_mcast_bytes,
+ "multicast bytes received");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "bcast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_bcast_bytes,
+ "broadcast bytes received");
+
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "tpa_pkts", CTLFLAG_RD, &rx_stats[rxr].tpa_pkts,
+ "TPA packets");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "tpa_bytes", CTLFLAG_RD, &rx_stats[rxr].tpa_bytes,
+ "TPA bytes");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "tpa_events", CTLFLAG_RD, &rx_stats[rxr].tpa_events,
+ "TPA events");
+ SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "tpa_aborts", CTLFLAG_RD, &rx_stats[rxr].tpa_aborts,
+ "TPA aborts");
+
+ return 0;
+}
+
+static char *bnxt_chip_type[] = {
+ "ASIC",
+ "FPGA",
+ "Palladium",
+ "Unknown"
+};
+#define MAX_CHIP_TYPE 3
+
+static int
+bnxt_package_ver_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct bnxt_softc *softc = arg1;
+ struct iflib_dma_info dma_data;
+ char *pkglog = NULL;
+ char *p;
+ char *next;
+ char unk[] = "<unknown>";
+ char *buf = unk;
+ int rc;
+ int field;
+ uint16_t ordinal = BNX_DIR_ORDINAL_FIRST;
+ uint16_t index;
+ uint32_t data_len;
+
+ rc = bnxt_hwrm_nvm_find_dir_entry(softc, BNX_DIR_TYPE_PKG_LOG,
+ &ordinal, BNX_DIR_EXT_NONE, &index, false,
+ HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_EQ,
+ &data_len, NULL, NULL);
+ dma_data.idi_vaddr = NULL;
+ if (rc == 0 && data_len) {
+ rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data,
+ BUS_DMA_NOWAIT);
+ if (rc == 0) {
+ rc = bnxt_hwrm_nvm_read(softc, index, 0, data_len,
+ &dma_data);
+ if (rc == 0) {
+ pkglog = dma_data.idi_vaddr;
+ /* NULL terminate (removes last \n) */
+ pkglog[data_len-1] = 0;
+
+ /* Set p = start of last line */
+ p = strrchr(pkglog, '\n');
+ if (p == NULL)
+ p = pkglog;
+
+ /* Now find the correct tab delimited field */
+ for (field = 0, next = p,
+ p = strsep(&next, "\t");
+ field <
+ BNX_PKG_LOG_FIELD_IDX_PKG_VERSION && p;
+ p = strsep(&next, "\t")) {
+ field++;
+ }
+ if (field == BNX_PKG_LOG_FIELD_IDX_PKG_VERSION)
+ buf = p;
+ }
+ }
+ else
+ dma_data.idi_vaddr = NULL;
+ }
+
+ rc = sysctl_handle_string(oidp, buf, 0, req);
+ if (dma_data.idi_vaddr)
+ iflib_dma_free(&dma_data);
+ return rc;
+}
+
+static int
+bnxt_hwrm_min_ver_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct bnxt_softc *softc = arg1;
+ char buf[16];
+ uint8_t newver[3];
+ int rc;
+
+ sprintf(buf, "%hhu.%hhu.%hhu", softc->ver_info->hwrm_min_major,
+ softc->ver_info->hwrm_min_minor, softc->ver_info->hwrm_min_update);
+
+ rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ if (rc || req->newptr == NULL)
+ return rc;
+ if (sscanf(buf, "%hhu.%hhu.%hhu%*c", &newver[0], &newver[1],
+ &newver[2]) != 3)
+ return EINVAL;
+ softc->ver_info->hwrm_min_major = newver[0];
+ softc->ver_info->hwrm_min_minor = newver[1];
+ softc->ver_info->hwrm_min_update = newver[2];
+ bnxt_check_hwrm_version(softc);
+
+ return rc;
+}
+
+int
+bnxt_create_ver_sysctls(struct bnxt_softc *softc)
+{
+ struct bnxt_ver_info *vi = softc->ver_info;
+ struct sysctl_oid *oid = vi->ver_oid;
+
+ if (!oid)
+ return ENOMEM;
+
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "hwrm_if", CTLFLAG_RD, vi->hwrm_if_ver, 0,
+ "HWRM interface version");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "driver_hwrm_if", CTLFLAG_RD, vi->driver_hwrm_if_ver, 0,
+ "HWRM firmware version");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "hwrm_fw", CTLFLAG_RD, vi->hwrm_fw_ver, 0,
+ "HWRM firmware version");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "mgmt_fw", CTLFLAG_RD, vi->mgmt_fw_ver, 0,
+ "management firmware version");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "netctrl_fw", CTLFLAG_RD, vi->netctrl_fw_ver, 0,
+ "network control firmware version");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "roce_fw", CTLFLAG_RD, vi->roce_fw_ver, 0,
+ "RoCE firmware version");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "phy", CTLFLAG_RD, vi->phy_ver, 0,
+ "PHY version");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "hwrm_fw_name", CTLFLAG_RD, vi->hwrm_fw_name, 0,
+ "HWRM firmware name");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "mgmt_fw_name", CTLFLAG_RD, vi->mgmt_fw_name, 0,
+ "management firmware name");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "netctrl_fw_name", CTLFLAG_RD, vi->netctrl_fw_name, 0,
+ "network control firmware name");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "roce_fw_name", CTLFLAG_RD, vi->roce_fw_name, 0,
+ "RoCE firmware name");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "phy_vendor", CTLFLAG_RD, vi->phy_vendor, 0,
+ "PHY vendor name");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "phy_partnumber", CTLFLAG_RD, vi->phy_partnumber, 0,
+ "PHY vendor part number");
+ SYSCTL_ADD_U16(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "chip_num", CTLFLAG_RD, &vi->chip_num, 0, "chip number");
+ SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "chip_rev", CTLFLAG_RD, &vi->chip_rev, 0, "chip revision");
+ SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "chip_metal", CTLFLAG_RD, &vi->chip_metal, 0, "chip metal number");
+ SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "chip_bond_id", CTLFLAG_RD, &vi->chip_bond_id, 0,
+ "chip bond id");
+ SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "chip_type", CTLFLAG_RD, vi->chip_type > MAX_CHIP_TYPE ?
+ bnxt_chip_type[MAX_CHIP_TYPE] : bnxt_chip_type[vi->chip_type], 0,
+ "RoCE firmware name");
+ SYSCTL_ADD_PROC(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "package_ver", CTLTYPE_STRING|CTLFLAG_RD, softc, 0,
+ bnxt_package_ver_sysctl, "A",
+ "currently installed package version");
+ SYSCTL_ADD_PROC(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "hwrm_min_ver", CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0,
+ bnxt_hwrm_min_ver_sysctl, "A",
+ "minimum hwrm API vesion to support");
+
+ return 0;
+}
+
+int
+bnxt_create_nvram_sysctls(struct bnxt_nvram_info *ni)
+{
+ struct sysctl_oid *oid = ni->nvm_oid;
+
+ if (!oid)
+ return ENOMEM;
+
+ SYSCTL_ADD_U16(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "mfg_id", CTLFLAG_RD, &ni->mfg_id, 0, "manufacturer id");
+ SYSCTL_ADD_U16(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "device_id", CTLFLAG_RD, &ni->device_id, 0, "device id");
+ SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "sector_size", CTLFLAG_RD, &ni->sector_size, 0, "sector size");
+ SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "size", CTLFLAG_RD, &ni->size, 0, "nvram total size");
+ SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "reserved_size", CTLFLAG_RD, &ni->reserved_size, 0,
+ "total reserved space");
+ SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "available_size", CTLFLAG_RD, &ni->available_size, 0,
+ "total available space");
+
+ return 0;
+}
+
+static int
+bnxt_rss_key_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct bnxt_softc *softc = arg1;
+ char buf[HW_HASH_KEY_SIZE*2+1] = {0};
+ char *p;
+ int i;
+ int rc;
+
+ for (p = buf, i=0; i<HW_HASH_KEY_SIZE; i++)
+ p += sprintf(p, "%02x", softc->vnic_info.rss_hash_key[i]);
+
+ rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ if (rc || req->newptr == NULL)
+ return rc;
+
+ if (strspn(buf, "0123456789abcdefABCDEF") != (HW_HASH_KEY_SIZE * 2))
+ return EINVAL;
+
+ for (p = buf, i=0; i<HW_HASH_KEY_SIZE; i++) {
+ if (sscanf(p, "%02hhx", &softc->vnic_info.rss_hash_key[i]) != 1)
+ return EINVAL;
+ p += 2;
+ }
+
+ if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING)
+ bnxt_hwrm_rss_cfg(softc, &softc->vnic_info,
+ softc->vnic_info.rss_hash_type);
+
+ return rc;
+}
+
+static const char *bnxt_hash_types[] = {"ipv4", "tcp_ipv4", "udp_ipv4", "ipv6",
+ "tcp_ipv6", "udp_ipv6", NULL};
+
+static int bnxt_get_rss_type_str_bit(char *str)
+{
+ int i;
+
+ for (i=0; bnxt_hash_types[i]; i++)
+ if (strcmp(bnxt_hash_types[i], str) == 0)
+ return i;
+
+ return -1;
+}
+
+static int
+bnxt_rss_type_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct bnxt_softc *softc = arg1;
+ char buf[256] = {0};
+ char *p;
+ char *next;
+ int rc;
+ int type;
+ int bit;
+
+ for (type = softc->vnic_info.rss_hash_type; type;
+ type &= ~(1<<bit)) {
+ bit = ffs(type) - 1;
+ if (bit >= sizeof(bnxt_hash_types) / sizeof(const char *))
+ continue;
+ if (type != softc->vnic_info.rss_hash_type)
+ strcat(buf, ",");
+ strcat(buf, bnxt_hash_types[bit]);
+ }
+
+ rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ if (rc || req->newptr == NULL)
+ return rc;
+
+ for (type = 0, next = buf, p = strsep(&next, " ,"); p;
+ p = strsep(&next, " ,")) {
+ bit = bnxt_get_rss_type_str_bit(p);
+ if (bit == -1)
+ return EINVAL;
+ type |= 1<<bit;
+ }
+ if (type != softc->vnic_info.rss_hash_type) {
+ softc->vnic_info.rss_hash_type = type;
+ if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING)
+ bnxt_hwrm_rss_cfg(softc, &softc->vnic_info,
+ softc->vnic_info.rss_hash_type);
+ }
+
+ return rc;
+}
+
+static int
+bnxt_rx_stall_sysctl(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = (bool)(softc->vnic_info.flags & BNXT_VNIC_FLAG_BD_STALL);
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ if (val)
+ softc->vnic_info.flags |= BNXT_VNIC_FLAG_BD_STALL;
+ else
+ softc->vnic_info.flags &= ~BNXT_VNIC_FLAG_BD_STALL;
+
+ if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING)
+ rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info);
+
+ return rc;
+}
+
+static int
+bnxt_vlan_strip_sysctl(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = (bool)(softc->vnic_info.flags & BNXT_VNIC_FLAG_VLAN_STRIP);
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ if (val)
+ softc->vnic_info.flags |= BNXT_VNIC_FLAG_VLAN_STRIP;
+ else
+ softc->vnic_info.flags &= ~BNXT_VNIC_FLAG_VLAN_STRIP;
+
+ if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING)
+ rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info);
+
+ return rc;
+}
+
+int
+bnxt_create_config_sysctls_pre(struct bnxt_softc *softc)
+{
+ struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(softc->dev);
+ struct sysctl_oid_list *children;
+
+ children = SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev));;
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rss_key",
+ CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0, bnxt_rss_key_sysctl, "A",
+ "RSS key");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rss_type",
+ CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0, bnxt_rss_type_sysctl, "A",
+ "RSS type bits");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_stall",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_rx_stall_sysctl, "I",
+ "buffer rx packets in hardware until the host posts new buffers");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "vlan_strip",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_vlan_strip_sysctl, "I",
+ "strip VLAN tag in the RX path");
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "if_name", CTLFLAG_RD,
+ iflib_get_ifp(softc->ctx)->if_xname, 0, "interface name");
+
+ return 0;
+}
+
+static int
+bnxt_vlan_only_sysctl(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = softc->vnic_info.vlan_only;
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ if (val)
+ val = 1;
+
+ if (val != softc->vnic_info.vlan_only) {
+ softc->vnic_info.vlan_only = val;
+ if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING)
+ rc = bnxt_hwrm_cfa_l2_set_rx_mask(softc,
+ &softc->vnic_info);
+ }
+
+ return rc;
+}
+
+int
+bnxt_create_config_sysctls_post(struct bnxt_softc *softc)
+{
+ struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(softc->dev);
+ struct sysctl_oid_list *children;
+
+ children = SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev));;
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "vlan_only",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_vlan_only_sysctl, "I",
+ "require vlan tag on received packets when vlan is enabled");
+
+ return 0;
+}
diff --git a/sys/dev/bnxt/bnxt_sysctl.h b/sys/dev/bnxt/bnxt_sysctl.h
new file mode 100644
index 000000000000..62b7dcf1e37c
--- /dev/null
+++ b/sys/dev/bnxt/bnxt_sysctl.h
@@ -0,0 +1,41 @@
+/*-
+ * Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 "bnxt.h"
+
+int bnxt_init_sysctl_ctx(struct bnxt_softc *softc);
+int bnxt_free_sysctl_ctx(struct bnxt_softc *softc);
+int bnxt_create_tx_sysctls(struct bnxt_softc *softc, int txr);
+int bnxt_create_rx_sysctls(struct bnxt_softc *softc, int rxr);
+int bnxt_create_ver_sysctls(struct bnxt_softc *softc);
+int bnxt_create_nvram_sysctls(struct bnxt_nvram_info *ni);
+int bnxt_create_config_sysctls_pre(struct bnxt_softc *softc);
+int bnxt_create_config_sysctls_post(struct bnxt_softc *softc);
diff --git a/sys/dev/bnxt/bnxt_txrx.c b/sys/dev/bnxt/bnxt_txrx.c
new file mode 100644
index 000000000000..b3e8a12b71bd
--- /dev/null
+++ b/sys/dev/bnxt/bnxt_txrx.c
@@ -0,0 +1,641 @@
+/*-
+ * Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/endian.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/ethernet.h>
+#include <net/iflib.h>
+
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_rss.h"
+
+#include "bnxt.h"
+
+/*
+ * Function prototypes
+ */
+
+static int bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi);
+static void bnxt_isc_txd_flush(void *sc, uint16_t txqid, uint32_t pidx);
+static int bnxt_isc_txd_credits_update(void *sc, uint16_t txqid, uint32_t cidx,
+ bool clear);
+
+static void bnxt_isc_rxd_refill(void *sc, uint16_t rxqid, uint8_t flid,
+ uint32_t pidx, uint64_t *paddrs, caddr_t *vaddrs, uint16_t count,
+ uint16_t buf_size);
+static void bnxt_isc_rxd_flush(void *sc, uint16_t rxqid, uint8_t flid,
+ uint32_t pidx);
+static int bnxt_isc_rxd_available(void *sc, uint16_t rxqid, uint32_t idx,
+ int budget);
+static int bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_t ri);
+
+static int bnxt_intr(void *sc);
+
+struct if_txrx bnxt_txrx = {
+ bnxt_isc_txd_encap,
+ bnxt_isc_txd_flush,
+ bnxt_isc_txd_credits_update,
+ bnxt_isc_rxd_available,
+ bnxt_isc_rxd_pkt_get,
+ bnxt_isc_rxd_refill,
+ bnxt_isc_rxd_flush,
+ bnxt_intr
+};
+
+/*
+ * Device Dependent Packet Transmit and Receive Functions
+ */
+
+static const uint16_t bnxt_tx_lhint[] = {
+ TX_BD_SHORT_FLAGS_LHINT_LT512,
+ TX_BD_SHORT_FLAGS_LHINT_LT1K,
+ TX_BD_SHORT_FLAGS_LHINT_LT2K,
+ TX_BD_SHORT_FLAGS_LHINT_LT2K,
+ TX_BD_SHORT_FLAGS_LHINT_GTE2K,
+};
+
+static int
+bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi)
+{
+ struct bnxt_softc *softc = (struct bnxt_softc *)sc;
+ struct bnxt_ring *txr = &softc->tx_rings[pi->ipi_qsidx];
+ struct tx_bd_long *tbd;
+ struct tx_bd_long_hi *tbdh;
+ bool need_hi = false;
+ uint16_t flags_type;
+ uint16_t lflags;
+ uint32_t cfa_meta;
+ int seg = 0;
+
+ /* If we have offloads enabled, we need to use two BDs. */
+ if ((pi->ipi_csum_flags & (CSUM_OFFLOAD | CSUM_TSO | CSUM_IP)) ||
+ pi->ipi_mflags & M_VLANTAG)
+ need_hi = true;
+
+ /* TODO: Devices before Cu+B1 need to not mix long and short BDs */
+ need_hi = true;
+
+ pi->ipi_new_pidx = pi->ipi_pidx;
+ tbd = &((struct tx_bd_long *)txr->vaddr)[pi->ipi_new_pidx];
+ pi->ipi_ndescs = 0;
+ /* No need to byte-swap the opaque value */
+ tbd->opaque = ((pi->ipi_nsegs + need_hi) << 24) | pi->ipi_new_pidx;
+ tbd->len = htole16(pi->ipi_segs[seg].ds_len);
+ tbd->addr = htole64(pi->ipi_segs[seg++].ds_addr);
+ flags_type = ((pi->ipi_nsegs + need_hi) <<
+ TX_BD_SHORT_FLAGS_BD_CNT_SFT) & TX_BD_SHORT_FLAGS_BD_CNT_MASK;
+ if (pi->ipi_len >= 2048)
+ flags_type |= TX_BD_SHORT_FLAGS_LHINT_GTE2K;
+ else
+ flags_type |= bnxt_tx_lhint[pi->ipi_len >> 9];
+
+ if (need_hi) {
+ flags_type |= TX_BD_LONG_TYPE_TX_BD_LONG;
+
+ pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx);
+ tbdh = &((struct tx_bd_long_hi *)txr->vaddr)[pi->ipi_new_pidx];
+ tbdh->mss = htole16(pi->ipi_tso_segsz);
+ tbdh->hdr_size = htole16((pi->ipi_ehdrlen + pi->ipi_ip_hlen +
+ pi->ipi_tcp_hlen) >> 1);
+ tbdh->cfa_action = 0;
+ lflags = 0;
+ cfa_meta = 0;
+ if (pi->ipi_mflags & M_VLANTAG) {
+ /* TODO: Do we need to byte-swap the vtag here? */
+ cfa_meta = TX_BD_LONG_CFA_META_KEY_VLAN_TAG |
+ pi->ipi_vtag;
+ cfa_meta |= TX_BD_LONG_CFA_META_VLAN_TPID_TPID8100;
+ }
+ tbdh->cfa_meta = htole32(cfa_meta);
+ if (pi->ipi_csum_flags & CSUM_TSO) {
+ lflags |= TX_BD_LONG_LFLAGS_LSO |
+ TX_BD_LONG_LFLAGS_T_IPID;
+ }
+ else if(pi->ipi_csum_flags & CSUM_OFFLOAD) {
+ lflags |= TX_BD_LONG_LFLAGS_TCP_UDP_CHKSUM |
+ TX_BD_LONG_LFLAGS_IP_CHKSUM;
+ }
+ else if(pi->ipi_csum_flags & CSUM_IP) {
+ lflags |= TX_BD_LONG_LFLAGS_IP_CHKSUM;
+ }
+ tbdh->lflags = htole16(lflags);
+ }
+ else {
+ flags_type |= TX_BD_SHORT_TYPE_TX_BD_SHORT;
+ }
+
+ for (; seg < pi->ipi_nsegs; seg++) {
+ tbd->flags_type = htole16(flags_type);
+ pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx);
+ tbd = &((struct tx_bd_long *)txr->vaddr)[pi->ipi_new_pidx];
+ tbd->len = htole16(pi->ipi_segs[seg].ds_len);
+ tbd->addr = htole64(pi->ipi_segs[seg].ds_addr);
+ flags_type = TX_BD_SHORT_TYPE_TX_BD_SHORT;
+ }
+ flags_type |= TX_BD_SHORT_FLAGS_PACKET_END;
+ tbd->flags_type = htole16(flags_type);
+ pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx);
+
+ return 0;
+}
+
+static void
+bnxt_isc_txd_flush(void *sc, uint16_t txqid, uint32_t pidx)
+{
+ struct bnxt_softc *softc = (struct bnxt_softc *)sc;
+ struct bnxt_ring *tx_ring = &softc->tx_rings[txqid];
+
+ /* pidx is what we last set ipi_new_pidx to */
+ BNXT_TX_DB(tx_ring, pidx);
+ /* TODO: Cumulus+ doesn't need the double doorbell */
+ BNXT_TX_DB(tx_ring, pidx);
+ return;
+}
+
+static int
+bnxt_isc_txd_credits_update(void *sc, uint16_t txqid, uint32_t idx, bool clear)
+{
+ struct bnxt_softc *softc = (struct bnxt_softc *)sc;
+ struct bnxt_cp_ring *cpr = &softc->tx_cp_rings[txqid];
+ struct tx_cmpl *cmpl = (struct tx_cmpl *)cpr->ring.vaddr;
+ int avail = 0;
+ uint32_t cons = cpr->cons;
+ bool v_bit = cpr->v_bit;
+ bool last_v_bit;
+ uint32_t last_cons;
+ uint16_t type;
+ uint16_t err;
+
+ for (;;) {
+ last_cons = cons;
+ last_v_bit = v_bit;
+ NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
+ CMPL_PREFETCH_NEXT(cpr, cons);
+
+ if (!CMP_VALID(&cmpl[cons], v_bit))
+ goto done;
+
+ type = cmpl[cons].flags_type & TX_CMPL_TYPE_MASK;
+ switch (type) {
+ case TX_CMPL_TYPE_TX_L2:
+ err = (le16toh(cmpl[cons].errors_v) &
+ TX_CMPL_ERRORS_BUFFER_ERROR_MASK) >>
+ TX_CMPL_ERRORS_BUFFER_ERROR_SFT;
+ if (err)
+ device_printf(softc->dev,
+ "TX completion error %u\n", err);
+ /* No need to byte-swap the opaque value */
+ avail += cmpl[cons].opaque >> 24;
+ /*
+ * If we're not clearing, iflib only cares if there's
+ * at least one buffer. Don't scan the whole ring in
+ * this case.
+ */
+ if (!clear)
+ goto done;
+ break;
+ default:
+ if (type & 1) {
+ NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
+ if (!CMP_VALID(&cmpl[cons], v_bit))
+ goto done;
+ }
+ device_printf(softc->dev,
+ "Unhandled TX completion type %u\n", type);
+ break;
+ }
+ }
+done:
+
+ if (clear && avail) {
+ cpr->cons = last_cons;
+ cpr->v_bit = last_v_bit;
+ BNXT_CP_IDX_DISABLE_DB(&cpr->ring, cpr->cons);
+ }
+
+ return avail;
+}
+
+static void
+bnxt_isc_rxd_refill(void *sc, uint16_t rxqid, uint8_t flid,
+ uint32_t pidx, uint64_t *paddrs,
+ caddr_t *vaddrs, uint16_t count, uint16_t len)
+{
+ struct bnxt_softc *softc = (struct bnxt_softc *)sc;
+ struct bnxt_ring *rx_ring;
+ struct rx_prod_pkt_bd *rxbd;
+ uint16_t type;
+ uint16_t i;
+
+ if (flid == 0) {
+ rx_ring = &softc->rx_rings[rxqid];
+ type = RX_PROD_PKT_BD_TYPE_RX_PROD_PKT;
+ }
+ else {
+ rx_ring = &softc->ag_rings[rxqid];
+ type = RX_PROD_AGG_BD_TYPE_RX_PROD_AGG;
+ }
+ rxbd = (void *)rx_ring->vaddr;
+
+ for (i=0; i<count; i++) {
+ rxbd[pidx].flags_type = htole16(type);
+ rxbd[pidx].len = htole16(len);
+ /* No need to byte-swap the opaque value */
+ rxbd[pidx].opaque = ((rxqid & 0xff) << 24) | (flid << 16)
+ | pidx;
+ rxbd[pidx].addr = htole64(paddrs[i]);
+ if (++pidx == rx_ring->ring_size)
+ pidx = 0;
+ }
+ return;
+}
+
+static void
+bnxt_isc_rxd_flush(void *sc, uint16_t rxqid, uint8_t flid,
+ uint32_t pidx)
+{
+ struct bnxt_softc *softc = (struct bnxt_softc *)sc;
+ struct bnxt_ring *rx_ring;
+
+ if (flid == 0)
+ rx_ring = &softc->rx_rings[rxqid];
+ else
+ rx_ring = &softc->ag_rings[rxqid];
+
+ /*
+ * We *must* update the completion ring before updating the RX ring
+ * or we will overrun the completion ring and the device will wedge for
+ * RX.
+ */
+ if (softc->rx_cp_rings[rxqid].cons != UINT32_MAX)
+ BNXT_CP_IDX_DISABLE_DB(&softc->rx_cp_rings[rxqid].ring,
+ softc->rx_cp_rings[rxqid].cons);
+ /* We're given the last filled RX buffer here, not the next empty one */
+ BNXT_RX_DB(rx_ring, RING_NEXT(rx_ring, pidx));
+ /* TODO: Cumulus+ doesn't need the double doorbell */
+ BNXT_RX_DB(rx_ring, RING_NEXT(rx_ring, pidx));
+ return;
+}
+
+static int
+bnxt_isc_rxd_available(void *sc, uint16_t rxqid, uint32_t idx, int budget)
+{
+ struct bnxt_softc *softc = (struct bnxt_softc *)sc;
+ struct bnxt_cp_ring *cpr = &softc->rx_cp_rings[rxqid];
+ struct rx_pkt_cmpl *rcp;
+ struct rx_tpa_start_cmpl *rtpa;
+ struct rx_tpa_end_cmpl *rtpae;
+ struct cmpl_base *cmp = (struct cmpl_base *)cpr->ring.vaddr;
+ int avail = 0;
+ uint32_t cons = cpr->cons;
+ bool v_bit = cpr->v_bit;
+ uint8_t ags;
+ int i;
+ uint16_t type;
+ uint8_t agg_id;
+
+ for (;;) {
+ NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
+ CMPL_PREFETCH_NEXT(cpr, cons);
+
+ if (!CMP_VALID(&cmp[cons], v_bit))
+ goto cmpl_invalid;
+
+ type = le16toh(cmp[cons].type) & CMPL_BASE_TYPE_MASK;
+ switch (type) {
+ case CMPL_BASE_TYPE_RX_L2:
+ rcp = (void *)&cmp[cons];
+ ags = (rcp->agg_bufs_v1 & RX_PKT_CMPL_AGG_BUFS_MASK) >>
+ RX_PKT_CMPL_AGG_BUFS_SFT;
+ NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
+ CMPL_PREFETCH_NEXT(cpr, cons);
+
+ if (!CMP_VALID(&cmp[cons], v_bit))
+ goto cmpl_invalid;
+
+ /* Now account for all the AG completions */
+ for (i=0; i<ags; i++) {
+ NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
+ CMPL_PREFETCH_NEXT(cpr, cons);
+ if (!CMP_VALID(&cmp[cons], v_bit))
+ goto cmpl_invalid;
+ }
+ avail++;
+ break;
+ case CMPL_BASE_TYPE_RX_TPA_END:
+ rtpae = (void *)&cmp[cons];
+ ags = (rtpae->agg_bufs_v1 &
+ RX_TPA_END_CMPL_AGG_BUFS_MASK) >>
+ RX_TPA_END_CMPL_AGG_BUFS_SFT;
+ NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
+ CMPL_PREFETCH_NEXT(cpr, cons);
+
+ if (!CMP_VALID(&cmp[cons], v_bit))
+ goto cmpl_invalid;
+ /* Now account for all the AG completions */
+ for (i=0; i<ags; i++) {
+ NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
+ CMPL_PREFETCH_NEXT(cpr, cons);
+ if (!CMP_VALID(&cmp[cons], v_bit))
+ goto cmpl_invalid;
+ }
+ avail++;
+ break;
+ case CMPL_BASE_TYPE_RX_TPA_START:
+ rtpa = (void *)&cmp[cons];
+ agg_id = (rtpa->agg_id &
+ RX_TPA_START_CMPL_AGG_ID_MASK) >>
+ RX_TPA_START_CMPL_AGG_ID_SFT;
+ softc->tpa_start[agg_id].low = *rtpa;
+ NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
+ CMPL_PREFETCH_NEXT(cpr, cons);
+
+ if (!CMP_VALID(&cmp[cons], v_bit))
+ goto cmpl_invalid;
+ softc->tpa_start[agg_id].high =
+ ((struct rx_tpa_start_cmpl_hi *)cmp)[cons];
+ break;
+ case CMPL_BASE_TYPE_RX_AGG:
+ break;
+ default:
+ device_printf(softc->dev,
+ "Unhandled completion type %d on RXQ %d\n",
+ type, rxqid);
+
+ /* Odd completion types use two completions */
+ if (type & 1) {
+ NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
+ CMPL_PREFETCH_NEXT(cpr, cons);
+
+ if (!CMP_VALID(&cmp[cons], v_bit))
+ goto cmpl_invalid;
+ }
+ break;
+ }
+ if (avail > budget)
+ break;
+ }
+cmpl_invalid:
+
+ return avail;
+}
+
+static int
+bnxt_pkt_get_l2(struct bnxt_softc *softc, if_rxd_info_t ri,
+ struct bnxt_cp_ring *cpr, uint16_t flags_type)
+{
+ struct rx_pkt_cmpl *rcp;
+ struct rx_pkt_cmpl_hi *rcph;
+ struct rx_abuf_cmpl *acp;
+ uint32_t flags2;
+ uint32_t errors;
+ uint8_t ags;
+ int i;
+
+ rcp = &((struct rx_pkt_cmpl *)cpr->ring.vaddr)[cpr->cons];
+
+ /* Extract from the first 16-byte BD */
+ if (flags_type & RX_PKT_CMPL_FLAGS_RSS_VALID) {
+ ri->iri_flowid = le32toh(rcp->rss_hash);
+ /*
+ * TODO: Extract something useful from rcp->rss_hash_type
+ * (undocumented)
+ * May be documented in the "LSI ES"
+ * also check the firmware code.
+ */
+ ri->iri_rsstype = M_HASHTYPE_OPAQUE;
+ }
+ else {
+ ri->iri_rsstype = M_HASHTYPE_NONE;
+ }
+ ags = (rcp->agg_bufs_v1 & RX_PKT_CMPL_AGG_BUFS_MASK) >>
+ RX_PKT_CMPL_AGG_BUFS_SFT;
+ ri->iri_nfrags = ags + 1;
+ /* No need to byte-swap the opaque value */
+ ri->iri_frags[0].irf_flid = (rcp->opaque >> 16) & 0xff;
+ ri->iri_frags[0].irf_idx = rcp->opaque & 0xffff;
+ ri->iri_frags[0].irf_len = le16toh(rcp->len);
+ ri->iri_len = le16toh(rcp->len);
+
+ /* Now the second 16-byte BD */
+ NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
+ ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
+ rcph = &((struct rx_pkt_cmpl_hi *)cpr->ring.vaddr)[cpr->cons];
+
+ flags2 = le32toh(rcph->flags2);
+ errors = le16toh(rcph->errors_v2);
+ if ((flags2 & RX_PKT_CMPL_FLAGS2_META_FORMAT_MASK) ==
+ RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN) {
+ ri->iri_flags |= M_VLANTAG;
+ /* TODO: Should this be the entire 16-bits? */
+ ri->iri_vtag = le32toh(rcph->metadata) &
+ (RX_PKT_CMPL_METADATA_VID_MASK | RX_PKT_CMPL_METADATA_DE |
+ RX_PKT_CMPL_METADATA_PRI_MASK);
+ }
+ if (flags2 & RX_PKT_CMPL_FLAGS2_IP_CS_CALC) {
+ ri->iri_csum_flags |= CSUM_IP_CHECKED;
+ if (!(errors & RX_PKT_CMPL_ERRORS_IP_CS_ERROR))
+ ri->iri_csum_flags |= CSUM_IP_VALID;
+ }
+ if (flags2 & RX_PKT_CMPL_FLAGS2_L4_CS_CALC) {
+ ri->iri_csum_flags |= CSUM_L4_CALC;
+ if (!(errors & RX_PKT_CMPL_ERRORS_L4_CS_ERROR)) {
+ ri->iri_csum_flags |= CSUM_L4_VALID;
+ ri->iri_csum_data = 0xffff;
+ }
+ }
+
+ /* And finally the ag ring stuff. */
+ for (i=1; i < ri->iri_nfrags; i++) {
+ NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
+ ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
+ acp = &((struct rx_abuf_cmpl *)cpr->ring.vaddr)[cpr->cons];
+
+ /* No need to byte-swap the opaque value */
+ ri->iri_frags[i].irf_flid = (acp->opaque >> 16 & 0xff);
+ ri->iri_frags[i].irf_idx = acp->opaque & 0xffff;
+ ri->iri_frags[i].irf_len = le16toh(acp->len);
+ ri->iri_len += le16toh(acp->len);
+ }
+
+ return 0;
+}
+
+static int
+bnxt_pkt_get_tpa(struct bnxt_softc *softc, if_rxd_info_t ri,
+ struct bnxt_cp_ring *cpr, uint16_t flags_type)
+{
+ struct rx_tpa_end_cmpl *agend =
+ &((struct rx_tpa_end_cmpl *)cpr->ring.vaddr)[cpr->cons];
+ struct rx_tpa_end_cmpl_hi *agendh;
+ struct rx_abuf_cmpl *acp;
+ struct bnxt_full_tpa_start *tpas;
+ uint32_t flags2;
+ uint8_t ags;
+ uint8_t agg_id;
+ int i;
+
+ /* Get the agg_id */
+ agg_id = (agend->agg_id & RX_TPA_END_CMPL_AGG_ID_MASK) >>
+ RX_TPA_END_CMPL_AGG_ID_SFT;
+ tpas = &softc->tpa_start[agg_id];
+
+ /* Extract from the first 16-byte BD */
+ if (le16toh(tpas->low.flags_type) & RX_TPA_START_CMPL_FLAGS_RSS_VALID) {
+ ri->iri_flowid = le32toh(tpas->low.rss_hash);
+ /*
+ * TODO: Extract something useful from tpas->low.rss_hash_type
+ * (undocumented)
+ * May be documented in the "LSI ES"
+ * also check the firmware code.
+ */
+ ri->iri_rsstype = M_HASHTYPE_OPAQUE;
+ }
+ else {
+ ri->iri_rsstype = M_HASHTYPE_NONE;
+ }
+ ags = (agend->agg_bufs_v1 & RX_TPA_END_CMPL_AGG_BUFS_MASK) >>
+ RX_TPA_END_CMPL_AGG_BUFS_SFT;
+ ri->iri_nfrags = ags + 1;
+ /* No need to byte-swap the opaque value */
+ ri->iri_frags[0].irf_flid = (tpas->low.opaque >> 16) & 0xff;
+ ri->iri_frags[0].irf_idx = tpas->low.opaque & 0xffff;
+ ri->iri_frags[0].irf_len = le16toh(tpas->low.len);
+ ri->iri_len = le16toh(tpas->low.len);
+
+ /* Now the second 16-byte BD */
+ NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
+ ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
+ agendh = &((struct rx_tpa_end_cmpl_hi *)cpr->ring.vaddr)[cpr->cons];
+
+ flags2 = le32toh(tpas->high.flags2);
+ if ((flags2 & RX_TPA_START_CMPL_FLAGS2_META_FORMAT_MASK) ==
+ RX_TPA_START_CMPL_FLAGS2_META_FORMAT_VLAN) {
+ ri->iri_flags |= M_VLANTAG;
+ /* TODO: Should this be the entire 16-bits? */
+ ri->iri_vtag = le32toh(tpas->high.metadata) &
+ (RX_TPA_START_CMPL_METADATA_VID_MASK |
+ RX_TPA_START_CMPL_METADATA_DE |
+ RX_TPA_START_CMPL_METADATA_PRI_MASK);
+ }
+ if (flags2 & RX_TPA_START_CMPL_FLAGS2_IP_CS_CALC) {
+ ri->iri_csum_flags |= CSUM_IP_CHECKED;
+ ri->iri_csum_flags |= CSUM_IP_VALID;
+ }
+ if (flags2 & RX_TPA_START_CMPL_FLAGS2_L4_CS_CALC) {
+ ri->iri_csum_flags |= CSUM_L4_CALC;
+ ri->iri_csum_flags |= CSUM_L4_VALID;
+ ri->iri_csum_data = 0xffff;
+ }
+
+ /* Now the ag ring stuff. */
+ for (i=1; i < ri->iri_nfrags; i++) {
+ NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
+ ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
+ acp = &((struct rx_abuf_cmpl *)cpr->ring.vaddr)[cpr->cons];
+
+ /* No need to byte-swap the opaque value */
+ ri->iri_frags[i].irf_flid = (acp->opaque >> 16) & 0xff;
+ ri->iri_frags[i].irf_idx = acp->opaque & 0xffff;
+ ri->iri_frags[i].irf_len = le16toh(acp->len);
+ ri->iri_len += le16toh(acp->len);
+ }
+
+ /* And finally, the empty BD at the end... */
+ ri->iri_nfrags++;
+ /* No need to byte-swap the opaque value */
+ ri->iri_frags[i].irf_flid = (agend->opaque >> 16) % 0xff;
+ ri->iri_frags[i].irf_idx = agend->opaque & 0xffff;
+ ri->iri_frags[i].irf_len = le16toh(agend->len);
+ ri->iri_len += le16toh(agend->len);
+
+ return 0;
+}
+
+/* If we return anything but zero, iflib will assert... */
+static int
+bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_t ri)
+{
+ struct bnxt_softc *softc = (struct bnxt_softc *)sc;
+ struct bnxt_cp_ring *cpr = &softc->rx_cp_rings[ri->iri_qsidx];
+ struct cmpl_base *cmp;
+ uint16_t flags_type;
+ uint16_t type;
+
+ for (;;) {
+ NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
+ ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
+ CMPL_PREFETCH_NEXT(cpr, cpr->cons);
+ cmp = &((struct cmpl_base *)cpr->ring.vaddr)[cpr->cons];
+
+ flags_type = le16toh(cmp->type);
+ type = flags_type & CMPL_BASE_TYPE_MASK;
+
+ switch (type) {
+ case CMPL_BASE_TYPE_RX_L2:
+ return bnxt_pkt_get_l2(softc, ri, cpr, flags_type);
+ case CMPL_BASE_TYPE_RX_TPA_END:
+ return bnxt_pkt_get_tpa(softc, ri, cpr, flags_type);
+ case CMPL_BASE_TYPE_RX_TPA_START:
+ NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit);
+ ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx);
+ CMPL_PREFETCH_NEXT(cpr, cpr->cons);
+ break;
+ default:
+ device_printf(softc->dev,
+ "Unhandled completion type %d on RXQ %d get\n",
+ type, ri->iri_qsidx);
+ if (type & 1) {
+ NEXT_CP_CONS_V(&cpr->ring, cpr->cons,
+ cpr->v_bit);
+ ri->iri_cidx = RING_NEXT(&cpr->ring,
+ ri->iri_cidx);
+ CMPL_PREFETCH_NEXT(cpr, cpr->cons);
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bnxt_intr(void *sc)
+{
+ struct bnxt_softc *softc = (struct bnxt_softc *)sc;
+
+ device_printf(softc->dev, "STUB: %s @ %s:%d\n", __func__, __FILE__, __LINE__);
+ return ENOSYS;
+}
diff --git a/sys/dev/bnxt/convert_hsi.pl b/sys/dev/bnxt/convert_hsi.pl
new file mode 100755
index 000000000000..b8a9887d7206
--- /dev/null
+++ b/sys/dev/bnxt/convert_hsi.pl
@@ -0,0 +1,356 @@
+#!/usr/bin/env perl
+
+# This script cleans up the "official" Broadcom hsi_struct_defs.h file as distributed
+# to something somewhat more programmer friendly.
+#
+# $FreeBSD$
+
+my $do_decode = 0;
+
+if (! -f $ARGV[0]) {
+ print "Input file not specified (should be path to hsi_struct_defs.h)\n";
+ exit 1;
+}
+
+if (!open(IN, "<", $ARGV[0])) {
+ print "Failure to open input file\n";
+ exit 1;
+}
+
+if (!open(OUT, ">", "hsi_struct_def.h")) {
+ print "Failure to open output file\n";
+ exit 1;
+}
+
+$/=undef;
+my $header = <IN>;
+close IN;
+
+print OUT <<END_OF_NOTICE;
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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\$");
+
+END_OF_NOTICE
+
+# Convert line endings
+$header =~ s/\r\n/\n/gs;
+
+# Convert arrays of two u32_t to a single uint64_t
+$header =~ s/\bu32_t(\s+[a-zA-Z0-9_]+)\[2\]/uint64_t$1/gs;
+
+# Convert uint32_t *_lo/uint32_t *_hi to a single uint64_t
+$header =~ s/\bu32_t(\s+[a-zA-Z0-9_]+)_lo;\s*\r?\n\s*u32_t(\s+[a-zA-Z0-9_]+)_hi/uint64_t$1/gs;
+
+# Convert types
+$header =~ s/\bu([0-9]+)_t\b/uint$1_t/gs;
+
+# Convert literals
+$header =~ s/\b((?:0x)?[0-9a-f]+)UL/UINT32_C($1)/gs;
+
+# Strip comments
+#$header =~ s/^(\s*[^\/\s][^\/]+?)\s*\/\*.*?\*\/\s*?$/$1/gm;
+#$header =~ s/[ \t]*\/\*.*?\*\/\s*?\n?//gs;
+
+# Pack structs
+#$header =~ s/}(\s+)([^\s]+_t[,;])/} __attribute__((packed))$1$2/gs;
+
+# Normalize indent
+$header =~ s/( ) +(#define)/$1$2/gs;
+$header =~ s/^(}[^\n]*;)\n([^\n])/$1\n\n$2/gsm;
+$header =~ s/([^\n])\n(typedef)/$1\n\n$2/gs;
+$header =~ s/ /\t/g;
+$header =~ s/ /\t/g;
+$header =~ s/([^\s]\t+) +/$1/g;
+
+# Remove typedefs and pack structs
+$header =~ s/^typedef struct (.*?)\n{\n(.*?)}[^\n]*;/struct $1 {\n$2} __attribute__((packed));/gsm;
+
+print OUT $header;
+close OUT;
+
+if ($do_decode) {
+ if(!open(OUT, ">", "hsi_struct_decode.c")) {
+ print "Failure to open decoder output file\n";
+ exit 1;
+ }
+
+ print OUT <<END_OF_NOTICE;
+ /*-
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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\$");
+
+END_OF_NOTICE
+
+ if(!open(HDR, ">", "hsi_struct_decode.h")) {
+ print "Failure to open decoder output header file\n";
+ exit 1;
+ }
+
+ print HDR <<END_OF_NOTICE;
+ /*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014-2015 Broadcom Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Broadcom Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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 MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER 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.
+ */
+
+END_OF_NOTICE
+
+ print OUT "#ifdef HSI_DEBUG\n#include <inttypes.h>\n#include <rte_common.h>\n#include <rte_log.h>\n#include \"hsi_struct_def_dpdk.h\"\n#include \"hsi_struct_decode.h\"\n#include \"hsi_struct_decode.h\"\n\n";
+ print HDR "#ifdef HSI_DEBUG\n#include \"hsi_struct_def_dpdk.h\"\n\n";
+
+ my $hdr_defs = '';
+
+ sub print_single_val
+ {
+ my $field=shift;
+ my $type=shift;
+ my $max_field_len=shift;
+ my $name = shift;
+ my $macroshash = shift;
+ my %macros = %$macroshash;
+ $macrosref = shift;
+ my @macros = @$macrosref;
+ $macrosref = shift;
+ my @fields = @$macrosref;
+
+ if ($type eq 'uint32_t') {
+ printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = 0x%%08\"PRIX32\"\\n\", data->$field);\n",$max_field_len,$field;
+ }
+ elsif ($type eq 'uint16_t') {
+ printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = 0x%%04\"PRIX16\"\\n\", data->$field);\n",$max_field_len,$field;
+ }
+ elsif ($type eq 'uint8_t') {
+ printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = 0x%%02\"PRIX8\"\\n\", data->$field);\n",$max_field_len,$field;
+ }
+ elsif ($type eq 'uint64_t') {
+ printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = 0x%%016\"PRIX64\"\\n\", data->$field);\n",$max_field_len,$field;
+ }
+ elsif ($type eq 'char') {
+ if ($field =~ s/\[([0-9]+)\]//) {
+ printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = \\\"%%.$1s\\\"\\n\", data->$field);\n",$max_field_len,$field;
+ }
+ else {
+ printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = 0x%%02\"PRIX8\"\\n\", data->$field);\n",$max_field_len,$field;
+ }
+ }
+ else {
+ print "Unhandled type: '$type'\n";
+ }
+
+ my $macro_prefix = uc($name).'_'.uc($field).'_';
+ # Special handling for the common flags_type field
+ $macro_prefix =~ s/FLAGS_TYPE_$/FLAGS_/ if ($field eq 'flags_type');
+ # Special handling for _hi types
+ $macro_prefix =~ s/_HI_/_/ if ($name =~ /_hi$/);
+
+ $macro_prefix =~ s/\[[0-9]+\]//;
+ my %vmacros;
+ my $vmacros_have_mask = 0;
+ my @vmacros;
+ my %subfields;
+ my $all_single_bits=1;
+ MACRO:
+ foreach my $macro (@macros) {
+ if ($macro =~ /^$macro_prefix(.*)_MASK$/) {
+ my $macro = $&;
+ my $maskdef = $macros{$macro};
+ my $subfield = $1;
+ my $subfield_value = "(data->$field & $macro)";
+ if (defined $macros{"$macro_prefix$subfield\_SFT"}) {
+ $subfield_value = "($subfield_value >> $macro_prefix$subfield\_SFT)";
+ }
+ $maskdef =~ s/[x0 ]//g;
+ if ($type eq 'uint64_t') {
+ printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s $subfield = %%0*\" PRIX64 \"\\n\", %u, $subfield_value);\n", $max_field_len, '', length($maskdef);
+ }
+ else {
+ printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s $subfield = %%0*X\\n\", %u, $subfield_value);\n", $max_field_len, '', length($maskdef);
+ }
+ delete $$macroshash{$macro};
+ }
+ elsif ($macro =~ /^$macro_prefix(.*)_SFT$/) {
+ delete $$macroshash{$macro};
+ }
+ elsif ($macro =~ /^$macro_prefix\MASK$/) {
+ $vmacros_have_mask = 1;
+ delete $$macroshash{$macro};
+ }
+ elsif ($macro =~ /^$macro_prefix(.*)$/) {
+ my $macro = $&;
+ my $subfield = $1;
+
+ # Check for longer fields with the same base... ie: link and link_speed
+ foreach my $extra_field (@fields) {
+ next if ($extra_field eq $field);
+ if ($extra_field =~ /^$field/) {
+ my $extra_prefix = uc($name).'_'.uc($extra_field).'_';
+ next MACRO if ($macro =~ /^$extra_prefix/);
+ }
+ }
+
+ push @vmacros, $macro;
+ my $macroeval = $macros{$macro};
+ $macroeval =~ s/UINT32_C\((.*?)\)/$1/g;
+ $vmacros{$macro} = eval("$macroeval");
+ $subfields{$macro} = $subfield;
+
+ $all_single_bits = 0 if ($vmacros{$macro} & ($vmacros{$macro}-1));
+ $all_single_bits = 0 if ($vmacros{$macro} == 0);
+ }
+ }
+ if ($all_single_bits) {
+ foreach my $macro (@vmacros) {
+ my $subfield_value = "(data->$field & $macro)";
+ printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s $subfields{$macro} : %%s\\n\", $subfield_value?\"ON\":\"OFF\");\n", $max_field_len, '';
+ delete $$macroshash{$macro};
+ }
+ }
+ else {
+ printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s Value : %%s\\n\",\n", $max_field_len, '';
+ foreach my $macro (@vmacros) {
+ my $subfield_value = "data->$field";
+ $subfield_value = "($subfield_value & $macro_prefix\MASK)" if $vmacros_have_mask;
+ print OUT "\t\t$subfield_value == $macro ? \"$subfields{$macro}\" :\n";
+ delete $$macroshash{$macro};
+ }
+ print OUT "\t\t\"Unknown\");\n";
+ }
+ }
+
+ while ($header =~ /^typedef\s+struct\s+(.*?)\s+{(.*?)^}/msg) {
+ my ($name,$def) = ($1, $2);
+ my @fields=();
+ my %type=();
+ my @macros=();
+ my %macros=();
+ my $max_field_len=0;
+
+ # First, pull out all the fields in order...
+ while($def =~ /^\s*([^\s#\/]+?)\s+([^;\/\s]+?)\s*;/mg) {
+ my ($type, $name) = ($1, $2);
+ push @fields, $name;
+ $type{$name}=$type;
+ $max_field_len = length($name) if length($name) > $max_field_len;
+ }
+ # Now, pull out the macros...
+ while($def =~ /^\s*\#define\s+([^\s]+?)\s+(.*?)\s*$/mg) {
+ push @macros, $1;
+ $macros{$1}=$2;
+ }
+
+ # Now, generate code to print the struct...
+ print OUT "void decode_$name(const char *string __rte_unused, struct $name *data) {\n\tRTE_LOG(DEBUG, PMD, \"$name\\n\");\n";
+ print HDR "void decode_$name(const char *string __rte_unused, struct $name *data);\n";
+ $hdr_defs .= "#define decode_$name(x, y) {}\n";
+ foreach my $field (@fields) {
+ if ($field =~ /\[([0-9]+)\]/) {
+ if ($type{$field} eq 'char') {
+ print_single_val($field, $type{$field}, $max_field_len, $name, \%macros, \@macros, \@fields);
+ }
+ else {
+ foreach my $idx (0..$1-1) {
+ my $item = $field;
+ $item =~ s/\[[0-9]+\]/[$idx]/;
+ print_single_val($item, $type{$field}, $max_field_len, $name, \%macros, \@macros, \@fields);
+ }
+ }
+ }
+ else {
+ print_single_val($field, $type{$field}, $max_field_len, $name, \%macros, \@macros, \@fields);
+ }
+ }
+ # print "Unhandled macros:\n",join("\n", keys %macros),"\n" if (keys %macros > 0);
+ print OUT "}\n\n";
+ }
+ print OUT "#endif\n";
+
+ print HDR "#else\n";
+ print HDR $hdr_defs;
+ print HDR "#endif\n";
+ close OUT;
+ close HDR;
+}
diff --git a/sys/dev/bnxt/hsi_struct_def.h b/sys/dev/bnxt/hsi_struct_def.h
new file mode 100644
index 000000000000..d55efee3e6c9
--- /dev/null
+++ b/sys/dev/bnxt/hsi_struct_def.h
@@ -0,0 +1,17576 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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$");
+
+/****************************************************************************
+ *
+ * Description: Definition of HSI data structures
+ *
+ * Date: 07/26/16 21:30:37
+ *
+ * Note: This file is scripted generated by hsi_decode.py.
+ * DO NOT modify this file manually !!!!
+ *
+ ****************************************************************************/
+#ifndef _HSI_STRUCT_DEF_EXTERNAL_H_
+#define _HSI_STRUCT_DEF_EXTERNAL_H_
+
+/*
+ * per-context HW statistics -- chip view
+ * Reference to stat_ctx_stat_xxx for
+ */
+
+struct ctx_hw_stats {
+ uint64_t rx_ucast_pkts;
+ uint64_t rx_mcast_pkts;
+ uint64_t rx_bcast_pkts;
+ uint64_t rx_discard_pkts;
+ uint64_t rx_drop_pkts;
+ uint64_t rx_ucast_bytes;
+ uint64_t rx_mcast_bytes;
+ uint64_t rx_bcast_bytes;
+ uint64_t tx_ucast_pkts;
+ uint64_t tx_mcast_pkts;
+ uint64_t tx_bcast_pkts;
+ uint64_t tx_discard_pkts;
+ uint64_t tx_drop_pkts;
+ uint64_t tx_ucast_bytes;
+ uint64_t tx_mcast_bytes;
+ uint64_t tx_bcast_bytes;
+ uint64_t tpa_pkts;
+ uint64_t tpa_bytes;
+ uint64_t tpa_events;
+ uint64_t tpa_aborts;
+} __attribute__((packed));
+
+/* BD Ring Structures */
+/*
+ * Description: This structure is used to inform the NIC of a location for and
+ * an aggregation buffer that will be used for packet data that is received. An
+ * aggregation buffer creates a different kind of completion operation for a
+ * packet where a variable number of BDs may be used to place the packet in the
+ * host. RX Rings that have aggregation buffers are known as aggregation rings
+ * and must contain only aggregation buffers.
+ */
+/*
+ * Note: BD Ring structures are written by the driver to TX Rings and RX Rings
+ * to indicate to the chip there is more buffer space in the host that needs to
+ * be transmitted or is available for receive data.
+ */
+/* BD Base (8 bytes) */
+
+struct bd_base {
+ uint8_t type;
+ /* This value identifies the type of buffer descriptor. */
+ #define BD_BASE_TYPE_MASK UINT32_C(0x3f)
+ #define BD_BASE_TYPE_SFT 0
+ /*
+ * Indicates that this BD is 16B long and is used for normal L2
+ * packet transmission.
+ */
+ #define BD_BASE_TYPE_TX_BD_SHORT UINT32_C(0x0)
+ /*
+ * Indicates that this BD is 1BB long and is an empty TX BD. Not
+ * valid for use by the driver.
+ */
+ #define BD_BASE_TYPE_TX_BD_EMPTY UINT32_C(0x1)
+ /*
+ * Indicates that this BD is 16B long and is an RX Producer (ie.
+ * empty) buffer descriptor.
+ */
+ #define BD_BASE_TYPE_RX_PROD_PKT UINT32_C(0x4)
+ /*
+ * Indicates that this BD is 16B long and is an RX Producer
+ * Buffer BD.
+ */
+ #define BD_BASE_TYPE_RX_PROD_BFR UINT32_C(0x5)
+ /*
+ * Indicates that this BD is 16B long and is an RX Producer
+ * Assembly Buffer Descriptor.
+ */
+ #define BD_BASE_TYPE_RX_PROD_AGG UINT32_C(0x6)
+ /*
+ * Indicates that this BD is 32B long and is used for normal L2
+ * packet transmission.
+ */
+ #define BD_BASE_TYPE_TX_BD_LONG UINT32_C(0x10)
+ uint8_t unused_1[7];
+} __attribute__((packed));
+
+/* Short TX BD (16 bytes) */
+
+struct tx_bd_short {
+ uint16_t flags_type;
+ /*
+ * All bits in this field must be valid on the first BD of a packet.
+ * Only the packet_end bit must be valid for the remaining BDs of a
+ * packet.
+ */
+ /* This value identifies the type of buffer descriptor. */
+ #define TX_BD_SHORT_TYPE_MASK UINT32_C(0x3f)
+ #define TX_BD_SHORT_TYPE_SFT 0
+ /*
+ * Indicates that this BD is 16B long and is used for normal L2
+ * packet transmission.
+ */
+ #define TX_BD_SHORT_TYPE_TX_BD_SHORT UINT32_C(0x0)
+ /*
+ * If set to 1, the packet ends with the data in the buffer pointed to
+ * by this descriptor. This flag must be valid on every BD.
+ */
+ #define TX_BD_SHORT_FLAGS_PACKET_END UINT32_C(0x40)
+ /*
+ * If set to 1, the device will not generate a completion for this
+ * transmit packet unless there is an error in it's processing. If this
+ * bit is set to 0, then the packet will be completed normally. This bit
+ * must be valid only on the first BD of a packet.
+ */
+ #define TX_BD_SHORT_FLAGS_NO_CMPL UINT32_C(0x80)
+ /*
+ * This value indicates how many 16B BD locations are consumed in the
+ * ring by this packet. A value of 1 indicates that this BD is the only
+ * BD (and that the it is a short BD). A value of 3 indicates either 3
+ * short BDs or 1 long BD and one short BD in the packet. A value of 0
+ * indicates that there are 32 BD locations in the packet (the maximum).
+ * This field is valid only on the first BD of a packet.
+ */
+ #define TX_BD_SHORT_FLAGS_BD_CNT_MASK UINT32_C(0x1f00)
+ #define TX_BD_SHORT_FLAGS_BD_CNT_SFT 8
+ /*
+ * This value is a hint for the length of the entire packet. It is used
+ * by the chip to optimize internal processing. The packet will be
+ * dropped if the hint is too short. This field is valid only on the
+ * first BD of a packet.
+ */
+ #define TX_BD_SHORT_FLAGS_LHINT_MASK UINT32_C(0x6000)
+ #define TX_BD_SHORT_FLAGS_LHINT_SFT 13
+ /* indicates packet length < 512B */
+ #define TX_BD_SHORT_FLAGS_LHINT_LT512 (UINT32_C(0x0) << 13)
+ /* indicates 512 <= packet length < 1KB */
+ #define TX_BD_SHORT_FLAGS_LHINT_LT1K (UINT32_C(0x1) << 13)
+ /* indicates 1KB <= packet length < 2KB */
+ #define TX_BD_SHORT_FLAGS_LHINT_LT2K (UINT32_C(0x2) << 13)
+ /* indicates packet length >= 2KB */
+ #define TX_BD_SHORT_FLAGS_LHINT_GTE2K (UINT32_C(0x3) << 13)
+ #define TX_BD_SHORT_FLAGS_LHINT_LAST TX_BD_SHORT_FLAGS_LHINT_GTE2K
+ /*
+ * If set to 1, the device immediately updates the Send Consumer Index
+ * after the buffer associated with this descriptor has been transferred
+ * via DMA to NIC memory from host memory. An interrupt may or may not
+ * be generated according to the state of the interrupt avoidance
+ * mechanisms. If this bit is set to 0, then the Consumer Index is only
+ * updated as soon as one of the host interrupt coalescing conditions
+ * has been met. This bit must be valid on the first BD of a packet.
+ */
+ #define TX_BD_SHORT_FLAGS_COAL_NOW UINT32_C(0x8000)
+ /*
+ * All bits in this field must be valid on the first BD of a packet.
+ * Only the packet_end bit must be valid for the remaining BDs of a
+ * packet.
+ */
+ #define TX_BD_SHORT_FLAGS_MASK UINT32_C(0xffc0)
+ #define TX_BD_SHORT_FLAGS_SFT 6
+ uint16_t len;
+ /*
+ * This is the length of the host physical buffer this BD describes in
+ * bytes. This field must be valid on all BDs of a packet.
+ */
+ uint32_t opaque;
+ /*
+ * The opaque data field is pass through to the completion and can be
+ * used for any data that the driver wants to associate with the
+ * transmit BD. This field must be valid on the first BD of a packet.
+ */
+ uint64_t addr;
+ /*
+ * This is the host physical address for the portion of the packet
+ * described by this TX BD. This value must be valid on all BDs of a
+ * packet.
+ */
+} __attribute__((packed));
+
+/* Long TX BD (32 bytes split to 2 16-byte struct) */
+
+struct tx_bd_long {
+ uint16_t flags_type;
+ /*
+ * All bits in this field must be valid on the first BD of a packet.
+ * Only the packet_end bit must be valid for the remaining BDs of a
+ * packet.
+ */
+ /* This value identifies the type of buffer descriptor. */
+ #define TX_BD_LONG_TYPE_MASK UINT32_C(0x3f)
+ #define TX_BD_LONG_TYPE_SFT 0
+ /*
+ * Indicates that this BD is 32B long and is used for normal L2
+ * packet transmission.
+ */
+ #define TX_BD_LONG_TYPE_TX_BD_LONG UINT32_C(0x10)
+ /*
+ * If set to 1, the packet ends with the data in the buffer pointed to
+ * by this descriptor. This flag must be valid on every BD.
+ */
+ #define TX_BD_LONG_FLAGS_PACKET_END UINT32_C(0x40)
+ /*
+ * If set to 1, the device will not generate a completion for this
+ * transmit packet unless there is an error in it's processing. If this
+ * bit is set to 0, then the packet will be completed normally. This bit
+ * must be valid only on the first BD of a packet.
+ */
+ #define TX_BD_LONG_FLAGS_NO_CMPL UINT32_C(0x80)
+ /*
+ * This value indicates how many 16B BD locations are consumed in the
+ * ring by this packet. A value of 1 indicates that this BD is the only
+ * BD (and that the it is a short BD). A value of 3 indicates either 3
+ * short BDs or 1 long BD and one short BD in the packet. A value of 0
+ * indicates that there are 32 BD locations in the packet (the maximum).
+ * This field is valid only on the first BD of a packet.
+ */
+ #define TX_BD_LONG_FLAGS_BD_CNT_MASK UINT32_C(0x1f00)
+ #define TX_BD_LONG_FLAGS_BD_CNT_SFT 8
+ /*
+ * This value is a hint for the length of the entire packet. It is used
+ * by the chip to optimize internal processing. The packet will be
+ * dropped if the hint is too short. This field is valid only on the
+ * first BD of a packet.
+ */
+ #define TX_BD_LONG_FLAGS_LHINT_MASK UINT32_C(0x6000)
+ #define TX_BD_LONG_FLAGS_LHINT_SFT 13
+ /* indicates packet length < 512B */
+ #define TX_BD_LONG_FLAGS_LHINT_LT512 (UINT32_C(0x0) << 13)
+ /* indicates 512 <= packet length < 1KB */
+ #define TX_BD_LONG_FLAGS_LHINT_LT1K (UINT32_C(0x1) << 13)
+ /* indicates 1KB <= packet length < 2KB */
+ #define TX_BD_LONG_FLAGS_LHINT_LT2K (UINT32_C(0x2) << 13)
+ /* indicates packet length >= 2KB */
+ #define TX_BD_LONG_FLAGS_LHINT_GTE2K (UINT32_C(0x3) << 13)
+ #define TX_BD_LONG_FLAGS_LHINT_LAST TX_BD_LONG_FLAGS_LHINT_GTE2K
+ /*
+ * If set to 1, the device immediately updates the Send Consumer Index
+ * after the buffer associated with this descriptor has been transferred
+ * via DMA to NIC memory from host memory. An interrupt may or may not
+ * be generated according to the state of the interrupt avoidance
+ * mechanisms. If this bit is set to 0, then the Consumer Index is only
+ * updated as soon as one of the host interrupt coalescing conditions
+ * has been met. This bit must be valid on the first BD of a packet.
+ */
+ #define TX_BD_LONG_FLAGS_COAL_NOW UINT32_C(0x8000)
+ /*
+ * All bits in this field must be valid on the first BD of a packet.
+ * Only the packet_end bit must be valid for the remaining BDs of a
+ * packet.
+ */
+ #define TX_BD_LONG_FLAGS_MASK UINT32_C(0xffc0)
+ #define TX_BD_LONG_FLAGS_SFT 6
+ uint16_t len;
+ /*
+ * This is the length of the host physical buffer this BD describes in
+ * bytes. This field must be valid on all BDs of a packet.
+ */
+ uint32_t opaque;
+ /*
+ * The opaque data field is pass through to the completion and can be
+ * used for any data that the driver wants to associate with the
+ * transmit BD. This field must be valid on the first BD of a packet.
+ */
+ uint64_t addr;
+ /*
+ * This is the host physical address for the portion of the packet
+ * described by this TX BD. This value must be valid on all BDs of a
+ * packet.
+ */
+} __attribute__((packed));
+
+/* last 16 bytes of Long TX BD */
+
+struct tx_bd_long_hi {
+ uint16_t lflags;
+ /*
+ * All bits in this field must be valid on the first BD of a packet.
+ * Their value on other BDs of the packet will be ignored.
+ */
+ /*
+ * If set to 1, the controller replaces the TCP/UPD checksum fields of
+ * normal TCP/UPD checksum, or the inner TCP/UDP checksum field of the
+ * encapsulated TCP/UDP packets with the hardware calculated TCP/UDP
+ * checksum for the packet associated with this descriptor. The flag is
+ * ignored if the LSO flag is set. This bit must be valid on the first
+ * BD of a packet.
+ */
+ #define TX_BD_LONG_LFLAGS_TCP_UDP_CHKSUM UINT32_C(0x1)
+ /*
+ * If set to 1, the controller replaces the IP checksum of the normal
+ * packets, or the inner IP checksum of the encapsulated packets with
+ * the hardware calculated IP checksum for the packet associated with
+ * this descriptor. This bit must be valid on the first BD of a packet.
+ */
+ #define TX_BD_LONG_LFLAGS_IP_CHKSUM UINT32_C(0x2)
+ /*
+ * If set to 1, the controller will not append an Ethernet CRC to the
+ * end of the frame. This bit must be valid on the first BD of a packet.
+ * Packet must be 64B or longer when this flag is set. It is not useful
+ * to use this bit with any form of TX offload such as CSO or LSO. The
+ * intent is that the packet from the host already has a valid Ethernet
+ * CRC on the packet.
+ */
+ #define TX_BD_LONG_LFLAGS_NOCRC UINT32_C(0x4)
+ /*
+ * If set to 1, the device will record the time at which the packet was
+ * actually transmitted at the TX MAC. This bit must be valid on the
+ * first BD of a packet.
+ */
+ #define TX_BD_LONG_LFLAGS_STAMP UINT32_C(0x8)
+ /*
+ * If set to 1, The controller replaces the tunnel IP checksum field
+ * with hardware calculated IP checksum for the IP header of the packet
+ * associated with this descriptor. For outer UDP checksum, global outer
+ * UDP checksum TE_NIC register needs to be enabled. If the global outer
+ * UDP checksum TE_NIC register bit is set, outer UDP checksum will be
+ * calculated for the following cases: 1. Packets with tcp_udp_chksum
+ * flag set to offload checksum for inner packet AND the inner packet is
+ * TCP/UDP. If the inner packet is ICMP for example (non-TCP/UDP), even
+ * if the tcp_udp_chksum is set, the outer UDP checksum will not be
+ * calculated. 2. Packets with lso flag set which implies inner TCP
+ * checksum calculation as part of LSO operation.
+ */
+ #define TX_BD_LONG_LFLAGS_T_IP_CHKSUM UINT32_C(0x10)
+ /*
+ * If set to 1, the device will treat this packet with LSO(Large Send
+ * Offload) processing for both normal or encapsulated packets, which is
+ * a form of TCP segmentation. When this bit is 1, the hdr_size and mss
+ * fields must be valid. The driver doesn't need to set t_ip_chksum,
+ * ip_chksum, and tcp_udp_chksum flags since the controller will replace
+ * the appropriate checksum fields for segmented packets. When this bit
+ * is 1, the hdr_size and mss fields must be valid.
+ */
+ #define TX_BD_LONG_LFLAGS_LSO UINT32_C(0x20)
+ /*
+ * If set to zero when LSO is '1', then the IPID will be treated as a
+ * 16b number and will be wrapped if it exceeds a value of 0xffff. If
+ * set to one when LSO is '1', then the IPID will be treated as a 15b
+ * number and will be wrapped if it exceeds a value 0f 0x7fff.
+ */
+ #define TX_BD_LONG_LFLAGS_IPID_FMT UINT32_C(0x40)
+ /*
+ * If set to zero when LSO is '1', then the IPID of the tunnel IP header
+ * will not be modified during LSO operations. If set to one when LSO is
+ * '1', then the IPID of the tunnel IP header will be incremented for
+ * each subsequent segment of an LSO operation. The flag is ignored if
+ * the LSO packet is a normal (non-tunneled) TCP packet.
+ */
+ #define TX_BD_LONG_LFLAGS_T_IPID UINT32_C(0x80)
+ /*
+ * If set to '1', then the RoCE ICRC will be appended to the packet.
+ * Packet must be a valid RoCE format packet.
+ */
+ #define TX_BD_LONG_LFLAGS_ROCE_CRC UINT32_C(0x100)
+ /*
+ * If set to '1', then the FCoE CRC will be appended to the packet.
+ * Packet must be a valid FCoE format packet.
+ */
+ #define TX_BD_LONG_LFLAGS_FCOE_CRC UINT32_C(0x200)
+ uint16_t hdr_size;
+ /*
+ * When LSO is '1', this field must contain the offset of the TCP
+ * payload from the beginning of the packet in as 16b words. In case of
+ * encapsulated/tunneling packet, this field contains the offset of the
+ * inner TCP payload from beginning of the packet as 16-bit words. This
+ * value must be valid on the first BD of a packet.
+ */
+ #define TX_BD_LONG_HDR_SIZE_MASK UINT32_C(0x1ff)
+ #define TX_BD_LONG_HDR_SIZE_SFT 0
+ uint32_t mss;
+ /*
+ * This is the MSS value that will be used to do the LSO processing. The
+ * value is the length in bytes of the TCP payload for each segment
+ * generated by the LSO operation. This value must be valid on the first
+ * BD of a packet.
+ */
+ #define TX_BD_LONG_MSS_MASK UINT32_C(0x7fff)
+ #define TX_BD_LONG_MSS_SFT 0
+ uint16_t unused_2;
+ uint16_t cfa_action;
+ /*
+ * This value selects a CFA action to perform on the packet. Set this
+ * value to zero if no CFA action is desired. This value must be valid
+ * on the first BD of a packet.
+ */
+ uint32_t cfa_meta;
+ /*
+ * This value is action meta-data that defines CFA edit operations that
+ * are done in addition to any action editing.
+ */
+ /* When key=1, This is the VLAN tag VID value. */
+ #define TX_BD_LONG_CFA_META_VLAN_VID_MASK UINT32_C(0xfff)
+ #define TX_BD_LONG_CFA_META_VLAN_VID_SFT 0
+ /* When key=1, This is the VLAN tag DE value. */
+ #define TX_BD_LONG_CFA_META_VLAN_DE UINT32_C(0x1000)
+ /* When key=1, This is the VLAN tag PRI value. */
+ #define TX_BD_LONG_CFA_META_VLAN_PRI_MASK UINT32_C(0xe000)
+ #define TX_BD_LONG_CFA_META_VLAN_PRI_SFT 13
+ /* When key=1, This is the VLAN tag TPID select value. */
+ #define TX_BD_LONG_CFA_META_VLAN_TPID_MASK UINT32_C(0x70000)
+ #define TX_BD_LONG_CFA_META_VLAN_TPID_SFT 16
+ /* 0x88a8 */
+ #define TX_BD_LONG_CFA_META_VLAN_TPID_TPID88A8 (UINT32_C(0x0) << 16)
+ /* 0x8100 */
+ #define TX_BD_LONG_CFA_META_VLAN_TPID_TPID8100 (UINT32_C(0x1) << 16)
+ /* 0x9100 */
+ #define TX_BD_LONG_CFA_META_VLAN_TPID_TPID9100 (UINT32_C(0x2) << 16)
+ /* 0x9200 */
+ #define TX_BD_LONG_CFA_META_VLAN_TPID_TPID9200 (UINT32_C(0x3) << 16)
+ /* 0x9300 */
+ #define TX_BD_LONG_CFA_META_VLAN_TPID_TPID9300 (UINT32_C(0x4) << 16)
+ /* Value programmed in CFA VLANTPID register. */
+ #define TX_BD_LONG_CFA_META_VLAN_TPID_TPIDCFG (UINT32_C(0x5) << 16)
+ #define TX_BD_LONG_CFA_META_VLAN_TPID_LAST TX_BD_LONG_CFA_META_VLAN_TPID_TPIDCFG
+ /* When key=1, This is the VLAN tag TPID select value. */
+ #define TX_BD_LONG_CFA_META_VLAN_RESERVED_MASK UINT32_C(0xff80000)
+ #define TX_BD_LONG_CFA_META_VLAN_RESERVED_SFT 19
+ /*
+ * This field identifies the type of edit to be performed on the packet.
+ * This value must be valid on the first BD of a packet.
+ */
+ #define TX_BD_LONG_CFA_META_KEY_MASK UINT32_C(0xf0000000)
+ #define TX_BD_LONG_CFA_META_KEY_SFT 28
+ /* No editing */
+ #define TX_BD_LONG_CFA_META_KEY_NONE (UINT32_C(0x0) << 28)
+ /*
+ * - meta[17:16] - TPID select value (0 = 0x8100). - meta[15:12]
+ * - PRI/DE value. - meta[11:0] - VID value.
+ */
+ #define TX_BD_LONG_CFA_META_KEY_VLAN_TAG (UINT32_C(0x1) << 28)
+ #define TX_BD_LONG_CFA_META_KEY_LAST TX_BD_LONG_CFA_META_KEY_VLAN_TAG
+} __attribute__((packed));
+
+/* Empty TX BD (16 bytes) */
+
+struct tx_bd_empty {
+ uint8_t type;
+ /* This value identifies the type of buffer descriptor. */
+ #define TX_BD_EMPTY_TYPE_MASK UINT32_C(0x3f)
+ #define TX_BD_EMPTY_TYPE_SFT 0
+ /*
+ * Indicates that this BD is 1BB long and is an empty TX BD. Not
+ * valid for use by the driver.
+ */
+ #define TX_BD_EMPTY_TYPE_TX_BD_EMPTY UINT32_C(0x1)
+ uint8_t unused_1[3];
+ uint8_t unused_2;
+ uint8_t unused_3[3];
+ uint64_t unused_4;
+} __attribute__((packed));
+
+/* RX Producer Packet BD (16 bytes) */
+
+struct rx_prod_pkt_bd {
+ uint16_t flags_type;
+ /* This value identifies the type of buffer descriptor. */
+ #define RX_PROD_PKT_BD_TYPE_MASK UINT32_C(0x3f)
+ #define RX_PROD_PKT_BD_TYPE_SFT 0
+ /*
+ * Indicates that this BD is 16B long and is an RX Producer (ie.
+ * empty) buffer descriptor.
+ */
+ #define RX_PROD_PKT_BD_TYPE_RX_PROD_PKT UINT32_C(0x4)
+ /*
+ * If set to 1, the packet will be placed at the address plus 2B. The 2
+ * Bytes of padding will be written as zero.
+ */
+ /*
+ * This is intended to be used when the host buffer is cache-line
+ * aligned to produce packets that are easy to parse in host memory
+ * while still allowing writes to be cache line aligned.
+ */
+ #define RX_PROD_PKT_BD_FLAGS_SOP_PAD UINT32_C(0x40)
+ /*
+ * If set to 1, the packet write will be padded out to the nearest
+ * cache-line with zero value padding.
+ */
+ /*
+ * If receive buffers start/end on cache-line boundaries, this feature
+ * will ensure that all data writes on the PCI bus start/end on cache
+ * line boundaries.
+ */
+ #define RX_PROD_PKT_BD_FLAGS_EOP_PAD UINT32_C(0x80)
+ /*
+ * This value is the number of additional buffers in the ring that
+ * describe the buffer space to be consumed for the this packet. If the
+ * value is zero, then the packet must fit within the space described by
+ * this BD. If this value is 1 or more, it indicates how many additional
+ * "buffer" BDs are in the ring immediately following this BD to be used
+ * for the same network packet. Even if the packet to be placed does not
+ * need all the additional buffers, they will be consumed anyway.
+ */
+ #define RX_PROD_PKT_BD_FLAGS_BUFFERS_MASK UINT32_C(0x300)
+ #define RX_PROD_PKT_BD_FLAGS_BUFFERS_SFT 8
+ #define RX_PROD_PKT_BD_FLAGS_MASK UINT32_C(0xffc0)
+ #define RX_PROD_PKT_BD_FLAGS_SFT 6
+ uint16_t len;
+ /*
+ * This is the length in Bytes of the host physical buffer where data
+ * for the packet may be placed in host memory.
+ */
+ /*
+ * While this is a Byte resolution value, it is often advantageous to
+ * ensure that the buffers provided end on a host cache line.
+ */
+ uint32_t opaque;
+ /*
+ * The opaque data field is pass through to the completion and can be
+ * used for any data that the driver wants to associate with this
+ * receive buffer set.
+ */
+ uint64_t addr;
+ /*
+ * This is the host physical address where data for the packet may by
+ * placed in host memory.
+ */
+ /*
+ * While this is a Byte resolution value, it is often advantageous to
+ * ensure that the buffers provide start on a host cache line.
+ */
+} __attribute__((packed));
+
+/* RX Producer Buffer BD (16 bytes) */
+
+struct rx_prod_bfr_bd {
+ uint16_t flags_type;
+ /* This value identifies the type of buffer descriptor. */
+ #define RX_PROD_BFR_BD_TYPE_MASK UINT32_C(0x3f)
+ #define RX_PROD_BFR_BD_TYPE_SFT 0
+ /*
+ * Indicates that this BD is 16B long and is an RX Producer
+ * Buffer BD.
+ */
+ #define RX_PROD_BFR_BD_TYPE_RX_PROD_BFR UINT32_C(0x5)
+ #define RX_PROD_BFR_BD_FLAGS_MASK UINT32_C(0xffc0)
+ #define RX_PROD_BFR_BD_FLAGS_SFT 6
+ uint16_t len;
+ /*
+ * This is the length in Bytes of the host physical buffer where data
+ * for the packet may be placed in host memory.
+ */
+ /*
+ * While this is a Byte resolution value, it is often advantageous to
+ * ensure that the buffers provided end on a host cache line.
+ */
+ uint32_t opaque;
+ /* This field is not used. */
+ uint64_t addr;
+ /*
+ * This is the host physical address where data for the packet may by
+ * placed in host memory.
+ */
+ /*
+ * While this is a Byte resolution value, it is often advantageous to
+ * ensure that the buffers provide start on a host cache line.
+ */
+} __attribute__((packed));
+
+/* RX Producer Aggregation BD (16 bytes) */
+
+struct rx_prod_agg_bd {
+ uint16_t flags_type;
+ /* This value identifies the type of buffer descriptor. */
+ #define RX_PROD_AGG_BD_TYPE_MASK UINT32_C(0x3f)
+ #define RX_PROD_AGG_BD_TYPE_SFT 0
+ /*
+ * Indicates that this BD is 16B long and is an RX Producer
+ * Assembly Buffer Descriptor.
+ */
+ #define RX_PROD_AGG_BD_TYPE_RX_PROD_AGG UINT32_C(0x6)
+ /*
+ * If set to 1, the packet write will be padded out to the nearest
+ * cache-line with zero value padding.
+ */
+ /*
+ * If receive buffers start/end on cache-line boundaries, this feature
+ * will ensure that all data writes on the PCI bus end on cache line
+ * boundaries.
+ */
+ #define RX_PROD_AGG_BD_FLAGS_EOP_PAD UINT32_C(0x40)
+ #define RX_PROD_AGG_BD_FLAGS_MASK UINT32_C(0xffc0)
+ #define RX_PROD_AGG_BD_FLAGS_SFT 6
+ uint16_t len;
+ /*
+ * This is the length in Bytes of the host physical buffer where data
+ * for the packet may be placed in host memory.
+ */
+ /*
+ * While this is a Byte resolution value, it is often advantageous to
+ * ensure that the buffers provided end on a host cache line.
+ */
+ uint32_t opaque;
+ /*
+ * The opaque data field is pass through to the completion and can be
+ * used for any data that the driver wants to associate with this
+ * receive assembly buffer.
+ */
+ uint64_t addr;
+ /*
+ * This is the host physical address where data for the packet may by
+ * placed in host memory.
+ */
+ /*
+ * While this is a Byte resolution value, it is often advantageous to
+ * ensure that the buffers provide start on a host cache line.
+ */
+} __attribute__((packed));
+
+/* Completion Ring Structures */
+/* Note: This structure is used by the HWRM to communicate HWRM Error. */
+/* Base Completion Record (16 bytes) */
+
+struct cmpl_base {
+ uint16_t type;
+ /* unused is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define CMPL_BASE_TYPE_MASK UINT32_C(0x3f)
+ #define CMPL_BASE_TYPE_SFT 0
+ /* TX L2 completion: Completion of TX packet. Length = 16B */
+ #define CMPL_BASE_TYPE_TX_L2 UINT32_C(0x0)
+ /* RX L2 completion: Completion of and L2 RX packet. Length = 32B */
+ #define CMPL_BASE_TYPE_RX_L2 UINT32_C(0x11)
+ /*
+ * RX Aggregation Buffer completion : Completion of an L2
+ * aggregation buffer in support of TPA, HDS, or Jumbo packet
+ * completion. Length = 16B
+ */
+ #define CMPL_BASE_TYPE_RX_AGG UINT32_C(0x12)
+ /*
+ * RX L2 TPA Start Completion: Completion at the beginning of a
+ * TPA operation. Length = 32B
+ */
+ #define CMPL_BASE_TYPE_RX_TPA_START UINT32_C(0x13)
+ /*
+ * RX L2 TPA End Completion: Completion at the end of a TPA
+ * operation. Length = 32B
+ */
+ #define CMPL_BASE_TYPE_RX_TPA_END UINT32_C(0x15)
+ /*
+ * Statistics Ejection Completion: Completion of statistics data
+ * ejection buffer. Length = 16B
+ */
+ #define CMPL_BASE_TYPE_STAT_EJECT UINT32_C(0x1a)
+ /* HWRM Command Completion: Completion of an HWRM command. */
+ #define CMPL_BASE_TYPE_HWRM_DONE UINT32_C(0x20)
+ /* Forwarded HWRM Request */
+ #define CMPL_BASE_TYPE_HWRM_FWD_REQ UINT32_C(0x22)
+ /* Forwarded HWRM Response */
+ #define CMPL_BASE_TYPE_HWRM_FWD_RESP UINT32_C(0x24)
+ /* HWRM Asynchronous Event Information */
+ #define CMPL_BASE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* CQ Notification */
+ #define CMPL_BASE_TYPE_CQ_NOTIFICATION UINT32_C(0x30)
+ /* SRQ Threshold Event */
+ #define CMPL_BASE_TYPE_SRQ_EVENT UINT32_C(0x32)
+ /* DBQ Threshold Event */
+ #define CMPL_BASE_TYPE_DBQ_EVENT UINT32_C(0x34)
+ /* QP Async Notification */
+ #define CMPL_BASE_TYPE_QP_EVENT UINT32_C(0x38)
+ /* Function Async Notification */
+ #define CMPL_BASE_TYPE_FUNC_EVENT UINT32_C(0x3a)
+ /* unused is 10 b */
+ uint16_t info1;
+ /* info1 is 16 b */
+ uint32_t info2;
+ /* info2 is 32 b */
+ uint32_t info3_v;
+ /* info3 is 31 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define CMPL_BASE_V UINT32_C(0x1)
+ /* info3 is 31 b */
+ #define CMPL_BASE_INFO3_MASK UINT32_C(0xfffffffe)
+ #define CMPL_BASE_INFO3_SFT 1
+ uint32_t info4;
+ /* info4 is 32 b */
+} __attribute__((packed));
+
+/* TX Completion Record (16 bytes) */
+
+struct tx_cmpl {
+ uint16_t flags_type;
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define TX_CMPL_TYPE_MASK UINT32_C(0x3f)
+ #define TX_CMPL_TYPE_SFT 0
+ /* TX L2 completion: Completion of TX packet. Length = 16B */
+ #define TX_CMPL_TYPE_TX_L2 UINT32_C(0x0)
+ /*
+ * When this bit is '1', it indicates a packet that has an error of some
+ * type. Type of error is indicated in error_flags.
+ */
+ #define TX_CMPL_FLAGS_ERROR UINT32_C(0x40)
+ /*
+ * When this bit is '1', it indicates that the packet completed was
+ * transmitted using the push acceleration data provided by the driver.
+ * When this bit is '0', it indicates that the packet had not push
+ * acceleration data written or was executed as a normal packet even
+ * though push data was provided.
+ */
+ #define TX_CMPL_FLAGS_PUSH UINT32_C(0x80)
+ #define TX_CMPL_FLAGS_MASK UINT32_C(0xffc0)
+ #define TX_CMPL_FLAGS_SFT 6
+ uint16_t unused_0;
+ /* unused1 is 16 b */
+ uint32_t opaque;
+ /*
+ * This is a copy of the opaque field from the first TX BD of this
+ * transmitted packet.
+ */
+ uint16_t errors_v;
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define TX_CMPL_V UINT32_C(0x1)
+ /*
+ * This error indicates that there was some sort of problem with the BDs
+ * for the packet.
+ */
+ #define TX_CMPL_ERRORS_BUFFER_ERROR_MASK UINT32_C(0xe)
+ #define TX_CMPL_ERRORS_BUFFER_ERROR_SFT 1
+ /* No error */
+ #define TX_CMPL_ERRORS_BUFFER_ERROR_NO_ERROR (UINT32_C(0x0) << 1)
+ /* Bad Format: BDs were not formatted correctly. */
+ #define TX_CMPL_ERRORS_BUFFER_ERROR_BAD_FMT (UINT32_C(0x2) << 1)
+ #define TX_CMPL_ERRORS_BUFFER_ERROR_LAST TX_CMPL_ERRORS_BUFFER_ERROR_BAD_FMT
+ /*
+ * When this bit is '1', it indicates that the length of the packet was
+ * zero. No packet was transmitted.
+ */
+ #define TX_CMPL_ERRORS_ZERO_LENGTH_PKT UINT32_C(0x10)
+ /*
+ * When this bit is '1', it indicates that the packet was longer than
+ * the programmed limit in TDI. No packet was transmitted.
+ */
+ #define TX_CMPL_ERRORS_EXCESSIVE_BD_LENGTH UINT32_C(0x20)
+ /*
+ * When this bit is '1', it indicates that one or more of the BDs
+ * associated with this packet generated a PCI error. This probably
+ * means the address was not valid.
+ */
+ #define TX_CMPL_ERRORS_DMA_ERROR UINT32_C(0x40)
+ /*
+ * When this bit is '1', it indicates that the packet was longer than
+ * indicated by the hint. No packet was transmitted.
+ */
+ #define TX_CMPL_ERRORS_HINT_TOO_SHORT UINT32_C(0x80)
+ /*
+ * When this bit is '1', it indicates that the packet was dropped due to
+ * Poison TLP error on one or more of the TLPs in the PXP completion.
+ */
+ #define TX_CMPL_ERRORS_POISON_TLP_ERROR UINT32_C(0x100)
+ #define TX_CMPL_ERRORS_MASK UINT32_C(0xfffe)
+ #define TX_CMPL_ERRORS_SFT 1
+ uint16_t unused_1;
+ /* unused2 is 16 b */
+ uint32_t unused_2;
+ /* unused3 is 32 b */
+} __attribute__((packed));
+
+/* RX Packet Completion Record (32 bytes split to 2 16-byte struct) */
+
+struct rx_pkt_cmpl {
+ uint16_t flags_type;
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define RX_PKT_CMPL_TYPE_MASK UINT32_C(0x3f)
+ #define RX_PKT_CMPL_TYPE_SFT 0
+ /* RX L2 completion: Completion of and L2 RX packet. Length = 32B */
+ #define RX_PKT_CMPL_TYPE_RX_L2 UINT32_C(0x11)
+ /*
+ * When this bit is '1', it indicates a packet that has an error of some
+ * type. Type of error is indicated in error_flags.
+ */
+ #define RX_PKT_CMPL_FLAGS_ERROR UINT32_C(0x40)
+ /* This field indicates how the packet was placed in the buffer. */
+ #define RX_PKT_CMPL_FLAGS_PLACEMENT_MASK UINT32_C(0x380)
+ #define RX_PKT_CMPL_FLAGS_PLACEMENT_SFT 7
+ /* Normal: Packet was placed using normal algorithm. */
+ #define RX_PKT_CMPL_FLAGS_PLACEMENT_NORMAL (UINT32_C(0x0) << 7)
+ /* Jumbo: Packet was placed using jumbo algorithm. */
+ #define RX_PKT_CMPL_FLAGS_PLACEMENT_JUMBO (UINT32_C(0x1) << 7)
+ /*
+ * Header/Data Separation: Packet was placed using Header/Data
+ * separation algorithm. The separation location is indicated by
+ * the itype field.
+ */
+ #define RX_PKT_CMPL_FLAGS_PLACEMENT_HDS (UINT32_C(0x2) << 7)
+ #define RX_PKT_CMPL_FLAGS_PLACEMENT_LAST RX_PKT_CMPL_FLAGS_PLACEMENT_HDS
+ /* This bit is '1' if the RSS field in this completion is valid. */
+ #define RX_PKT_CMPL_FLAGS_RSS_VALID UINT32_C(0x400)
+ /* unused is 1 b */
+ /*
+ * This value indicates what the inner packet determined for the packet
+ * was.
+ */
+ #define RX_PKT_CMPL_FLAGS_ITYPE_MASK UINT32_C(0xf000)
+ #define RX_PKT_CMPL_FLAGS_ITYPE_SFT 12
+ /* Not Known: Indicates that the packet type was not known. */
+ #define RX_PKT_CMPL_FLAGS_ITYPE_NOT_KNOWN (UINT32_C(0x0) << 12)
+ /*
+ * IP Packet: Indicates that the packet was an IP packet, but
+ * further classification was not possible.
+ */
+ #define RX_PKT_CMPL_FLAGS_ITYPE_IP (UINT32_C(0x1) << 12)
+ /*
+ * TCP Packet: Indicates that the packet was IP and TCP. This
+ * indicates that the payload_offset field is valid.
+ */
+ #define RX_PKT_CMPL_FLAGS_ITYPE_TCP (UINT32_C(0x2) << 12)
+ /*
+ * UDP Packet: Indicates that the packet was IP and UDP. This
+ * indicates that the payload_offset field is valid.
+ */
+ #define RX_PKT_CMPL_FLAGS_ITYPE_UDP (UINT32_C(0x3) << 12)
+ /*
+ * FCoE Packet: Indicates that the packet was recognized as a
+ * FCoE. This also indicates that the payload_offset field is
+ * valid.
+ */
+ #define RX_PKT_CMPL_FLAGS_ITYPE_FCOE (UINT32_C(0x4) << 12)
+ /*
+ * RoCE Packet: Indicates that the packet was recognized as a
+ * RoCE. This also indicates that the payload_offset field is
+ * valid.
+ */
+ #define RX_PKT_CMPL_FLAGS_ITYPE_ROCE (UINT32_C(0x5) << 12)
+ /*
+ * ICMP Packet: Indicates that the packet was recognized as
+ * ICMP. This indicates that the payload_offset field is valid.
+ */
+ #define RX_PKT_CMPL_FLAGS_ITYPE_ICMP (UINT32_C(0x7) << 12)
+ /*
+ * PtP packet wo/timestamp: Indicates that the packet was
+ * recognized as a PtP packet.
+ */
+ #define RX_PKT_CMPL_FLAGS_ITYPE_PTP_WO_TIMESTAMP (UINT32_C(0x8) << 12)
+ /*
+ * PtP packet w/timestamp: Indicates that the packet was
+ * recognized as a PtP packet and that a timestamp was taken for
+ * the packet.
+ */
+ #define RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP (UINT32_C(0x9) << 12)
+ #define RX_PKT_CMPL_FLAGS_ITYPE_LAST RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP
+ #define RX_PKT_CMPL_FLAGS_MASK UINT32_C(0xffc0)
+ #define RX_PKT_CMPL_FLAGS_SFT 6
+ uint16_t len;
+ /*
+ * This is the length of the data for the packet stored in the buffer(s)
+ * identified by the opaque value. This includes the packet BD and any
+ * associated buffer BDs. This does not include the the length of any
+ * data places in aggregation BDs.
+ */
+ uint32_t opaque;
+ /*
+ * This is a copy of the opaque field from the RX BD this completion
+ * corresponds to.
+ */
+ uint8_t agg_bufs_v1;
+ /* unused1 is 2 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define RX_PKT_CMPL_V1 UINT32_C(0x1)
+ /*
+ * This value is the number of aggregation buffers that follow this
+ * entry in the completion ring that are a part of this packet. If the
+ * value is zero, then the packet is completely contained in the buffer
+ * space provided for the packet in the RX ring.
+ */
+ #define RX_PKT_CMPL_AGG_BUFS_MASK UINT32_C(0x3e)
+ #define RX_PKT_CMPL_AGG_BUFS_SFT 1
+ /* unused1 is 2 b */
+ uint8_t rss_hash_type;
+ /*
+ * This is the RSS hash type for the packet. The value is packed
+ * {tuple_extrac_op[1:0],rss_profile_id[4:0],tuple_extrac_op[2]}.
+ */
+ uint8_t payload_offset;
+ /*
+ * This value indicates the offset in bytes from the beginning of the
+ * packet where the inner payload starts. This value is valid for TCP,
+ * UDP, FCoE, and RoCE packets. A value of zero indicates that header is
+ * 256B into the packet.
+ */
+ uint8_t unused_1;
+ /* unused2 is 8 b */
+ uint32_t rss_hash;
+ /*
+ * This value is the RSS hash value calculated for the packet based on
+ * the mode bits and key value in the VNIC.
+ */
+} __attribute__((packed));
+
+/* last 16 bytes of RX Packet Completion Record */
+
+struct rx_pkt_cmpl_hi {
+ uint32_t flags2;
+ /*
+ * This indicates that the ip checksum was calculated for the inner
+ * packet and that the ip_cs_error field indicates if there was an
+ * error.
+ */
+ #define RX_PKT_CMPL_FLAGS2_IP_CS_CALC UINT32_C(0x1)
+ /*
+ * This indicates that the TCP, UDP or ICMP checksum was calculated for
+ * the inner packet and that the l4_cs_error field indicates if there
+ * was an error.
+ */
+ #define RX_PKT_CMPL_FLAGS2_L4_CS_CALC UINT32_C(0x2)
+ /*
+ * This indicates that the ip checksum was calculated for the tunnel
+ * header and that the t_ip_cs_error field indicates if there was an
+ * error.
+ */
+ #define RX_PKT_CMPL_FLAGS2_T_IP_CS_CALC UINT32_C(0x4)
+ /*
+ * This indicates that the UDP checksum was calculated for the tunnel
+ * packet and that the t_l4_cs_error field indicates if there was an
+ * error.
+ */
+ #define RX_PKT_CMPL_FLAGS2_T_L4_CS_CALC UINT32_C(0x8)
+ /* This value indicates what format the metadata field is. */
+ #define RX_PKT_CMPL_FLAGS2_META_FORMAT_MASK UINT32_C(0xf0)
+ #define RX_PKT_CMPL_FLAGS2_META_FORMAT_SFT 4
+ /* No metadata informtaion. Value is zero. */
+ #define RX_PKT_CMPL_FLAGS2_META_FORMAT_NONE (UINT32_C(0x0) << 4)
+ /*
+ * The metadata field contains the VLAN tag and TPID value. -
+ * metadata[11:0] contains the vlan VID value. - metadata[12]
+ * contains the vlan DE value. - metadata[15:13] contains the
+ * vlan PRI value. - metadata[31:16] contains the vlan TPID
+ * value.
+ */
+ #define RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN (UINT32_C(0x1) << 4)
+ #define RX_PKT_CMPL_FLAGS2_META_FORMAT_LAST RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN
+ /*
+ * This field indicates the IP type for the inner-most IP header. A
+ * value of '0' indicates IPv4. A value of '1' indicates IPv6. This
+ * value is only valid if itype indicates a packet with an IP header.
+ */
+ #define RX_PKT_CMPL_FLAGS2_IP_TYPE UINT32_C(0x100)
+ uint32_t metadata;
+ /*
+ * This is data from the CFA block as indicated by the meta_format
+ * field.
+ */
+ /* When meta_format=1, this value is the VLAN VID. */
+ #define RX_PKT_CMPL_METADATA_VID_MASK UINT32_C(0xfff)
+ #define RX_PKT_CMPL_METADATA_VID_SFT 0
+ /* When meta_format=1, this value is the VLAN DE. */
+ #define RX_PKT_CMPL_METADATA_DE UINT32_C(0x1000)
+ /* When meta_format=1, this value is the VLAN PRI. */
+ #define RX_PKT_CMPL_METADATA_PRI_MASK UINT32_C(0xe000)
+ #define RX_PKT_CMPL_METADATA_PRI_SFT 13
+ /* When meta_format=1, this value is the VLAN TPID. */
+ #define RX_PKT_CMPL_METADATA_TPID_MASK UINT32_C(0xffff0000)
+ #define RX_PKT_CMPL_METADATA_TPID_SFT 16
+ uint16_t errors_v2;
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define RX_PKT_CMPL_V2 UINT32_C(0x1)
+ /*
+ * This error indicates that there was some sort of problem with the BDs
+ * for the packet that was found after part of the packet was already
+ * placed. The packet should be treated as invalid.
+ */
+ #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_MASK UINT32_C(0xe)
+ #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_SFT 1
+ /* No buffer error */
+ #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_NO_BUFFER (UINT32_C(0x0) << 1)
+ /*
+ * Did Not Fit: Packet did not fit into packet buffer provided.
+ * For regular placement, this means the packet did not fit in
+ * the buffer provided. For HDS and jumbo placement, this means
+ * that the packet could not be placed into 7 physical buffers
+ * or less.
+ */
+ #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_DID_NOT_FIT (UINT32_C(0x1) << 1)
+ /*
+ * Not On Chip: All BDs needed for the packet were not on-chip
+ * when the packet arrived.
+ */
+ #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (UINT32_C(0x2) << 1)
+ /* Bad Format: BDs were not formatted correctly. */
+ #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_BAD_FORMAT (UINT32_C(0x3) << 1)
+ #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_LAST RX_PKT_CMPL_ERRORS_BUFFER_ERROR_BAD_FORMAT
+ /* This indicates that there was an error in the IP header checksum. */
+ #define RX_PKT_CMPL_ERRORS_IP_CS_ERROR UINT32_C(0x10)
+ /*
+ * This indicates that there was an error in the TCP, UDP or ICMP
+ * checksum.
+ */
+ #define RX_PKT_CMPL_ERRORS_L4_CS_ERROR UINT32_C(0x20)
+ /*
+ * This indicates that there was an error in the tunnel IP header
+ * checksum.
+ */
+ #define RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR UINT32_C(0x40)
+ /* This indicates that there was an error in the tunnel UDP checksum. */
+ #define RX_PKT_CMPL_ERRORS_T_L4_CS_ERROR UINT32_C(0x80)
+ /*
+ * This indicates that there was a CRC error on either an FCoE or RoCE
+ * packet. The itype indicates the packet type.
+ */
+ #define RX_PKT_CMPL_ERRORS_CRC_ERROR UINT32_C(0x100)
+ /*
+ * This indicates that there was an error in the tunnel portion of the
+ * packet when this field is non-zero.
+ */
+ #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_MASK UINT32_C(0xe00)
+ #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_SFT 9
+ /*
+ * No additional error occurred on the tunnel portion of the
+ * packet of the packet does not have a tunnel.
+ */
+ #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_NO_ERROR (UINT32_C(0x0) << 9)
+ /*
+ * Indicates that IP header version does not match expectation
+ * from L2 Ethertype for IPv4 and IPv6 in the tunnel header.
+ */
+ #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_VERSION (UINT32_C(0x1) << 9)
+ /*
+ * Indicates that header length is out of range in the tunnel
+ * header. Valid for IPv4.
+ */
+ #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_HDR_LEN (UINT32_C(0x2) << 9)
+ /*
+ * Indicates that the physical packet is shorter than that
+ * claimed by the PPPoE header length for a tunnel PPPoE packet.
+ */
+ #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_TUNNEL_TOTAL_ERROR (UINT32_C(0x3) << 9)
+ /*
+ * Indicates that physical packet is shorter than that claimed
+ * by the tunnel l3 header length. Valid for IPv4, or IPv6
+ * tunnel packet packets.
+ */
+ #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_IP_TOTAL_ERROR (UINT32_C(0x4) << 9)
+ /*
+ * Indicates that the physical packet is shorter than that
+ * claimed by the tunnel UDP header length for a tunnel UDP
+ * packet that is not fragmented.
+ */
+ #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_UDP_TOTAL_ERROR (UINT32_C(0x5) << 9)
+ /*
+ * indicates that the IPv4 TTL or IPv6 hop limit check have
+ * failed (e.g. TTL = 0) in the tunnel header. Valid for IPv4,
+ * and IPv6.
+ */
+ #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL (UINT32_C(0x6) << 9)
+ #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_LAST RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL
+ /*
+ * This indicates that there was an error in the inner portion of the
+ * packet when this field is non-zero.
+ */
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_MASK UINT32_C(0xf000)
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_SFT 12
+ /*
+ * No additional error occurred on the tunnel portion of the
+ * packet of the packet does not have a tunnel.
+ */
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_NO_ERROR (UINT32_C(0x0) << 12)
+ /*
+ * Indicates that IP header version does not match expectation
+ * from L2 Ethertype for IPv4 and IPv6 or that option other than
+ * VFT was parsed on FCoE packet.
+ */
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L3_BAD_VERSION (UINT32_C(0x1) << 12)
+ /*
+ * indicates that header length is out of range. Valid for IPv4
+ * and RoCE
+ */
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L3_BAD_HDR_LEN (UINT32_C(0x2) << 12)
+ /*
+ * indicates that the IPv4 TTL or IPv6 hop limit check have
+ * failed (e.g. TTL = 0). Valid for IPv4, and IPv6
+ */
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L3_BAD_TTL (UINT32_C(0x3) << 12)
+ /*
+ * Indicates that physical packet is shorter than that claimed
+ * by the l3 header length. Valid for IPv4, IPv6 packet or RoCE
+ * packets.
+ */
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_IP_TOTAL_ERROR (UINT32_C(0x4) << 12)
+ /*
+ * Indicates that the physical packet is shorter than that
+ * claimed by the UDP header length for a UDP packet that is not
+ * fragmented.
+ */
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_UDP_TOTAL_ERROR (UINT32_C(0x5) << 12)
+ /*
+ * Indicates that TCP header length > IP payload. Valid for TCP
+ * packets only.
+ */
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN (UINT32_C(0x6) << 12)
+ /* Indicates that TCP header length < 5. Valid for TCP. */
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN_TOO_SMALL (UINT32_C(0x7) << 12)
+ /*
+ * Indicates that TCP option headers result in a TCP header size
+ * that does not match data offset in TCP header. Valid for TCP.
+ */
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN (UINT32_C(0x8) << 12)
+ #define RX_PKT_CMPL_ERRORS_PKT_ERROR_LAST RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN
+ #define RX_PKT_CMPL_ERRORS_MASK UINT32_C(0xfffe)
+ #define RX_PKT_CMPL_ERRORS_SFT 1
+ uint16_t cfa_code;
+ /*
+ * This field identifies the CFA action rule that was used for this
+ * packet.
+ */
+ uint32_t reorder;
+ /*
+ * This value holds the reordering sequence number for the packet. If
+ * the reordering sequence is not valid, then this value is zero. The
+ * reordering domain for the packet is in the bottom 8 to 10b of the
+ * rss_hash value. The bottom 20b of this value contain the ordering
+ * domain value for the packet.
+ */
+ #define RX_PKT_CMPL_REORDER_MASK UINT32_C(0xffffff)
+ #define RX_PKT_CMPL_REORDER_SFT 0
+} __attribute__((packed));
+
+/* RX L2 TPA Start Completion Record (32 bytes split to 2 16-byte struct) */
+
+struct rx_tpa_start_cmpl {
+ uint16_t flags_type;
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define RX_TPA_START_CMPL_TYPE_MASK UINT32_C(0x3f)
+ #define RX_TPA_START_CMPL_TYPE_SFT 0
+ /*
+ * RX L2 TPA Start Completion: Completion at the beginning of a
+ * TPA operation. Length = 32B
+ */
+ #define RX_TPA_START_CMPL_TYPE_RX_TPA_START UINT32_C(0x13)
+ /* This bit will always be '0' for TPA start completions. */
+ #define RX_TPA_START_CMPL_FLAGS_ERROR UINT32_C(0x40)
+ /* This field indicates how the packet was placed in the buffer. */
+ #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_MASK UINT32_C(0x380)
+ #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_SFT 7
+ /*
+ * Jumbo: TPA Packet was placed using jumbo algorithm. This
+ * means that the first buffer will be filled with data before
+ * moving to aggregation buffers. Each aggregation buffer will
+ * be filled before moving to the next aggregation buffer.
+ */
+ #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_JUMBO (UINT32_C(0x1) << 7)
+ /*
+ * Header/Data Separation: Packet was placed using Header/Data
+ * separation algorithm. The separation location is indicated by
+ * the itype field.
+ */
+ #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_HDS (UINT32_C(0x2) << 7)
+ /*
+ * GRO/Jumbo: Packet will be placed using GRO/Jumbo where the
+ * first packet is filled with data. Subsequent packets will be
+ * placed such that any one packet does not span two aggregation
+ * buffers unless it starts at the beginning of an aggregation
+ * buffer.
+ */
+ #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_GRO_JUMBO (UINT32_C(0x5) << 7)
+ /*
+ * GRO/Header-Data Separation: Packet will be placed using
+ * GRO/HDS where the header is in the first packet. Payload of
+ * each packet will be placed such that any one packet does not
+ * span two aggregation buffers unless it starts at the
+ * beginning of an aggregation buffer.
+ */
+ #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_GRO_HDS (UINT32_C(0x6) << 7)
+ #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_LAST RX_TPA_START_CMPL_FLAGS_PLACEMENT_GRO_HDS
+ /* This bit is '1' if the RSS field in this completion is valid. */
+ #define RX_TPA_START_CMPL_FLAGS_RSS_VALID UINT32_C(0x400)
+ /* unused is 1 b */
+ /*
+ * This value indicates what the inner packet determined for the packet
+ * was.
+ */
+ #define RX_TPA_START_CMPL_FLAGS_ITYPE_MASK UINT32_C(0xf000)
+ #define RX_TPA_START_CMPL_FLAGS_ITYPE_SFT 12
+ /* TCP Packet: Indicates that the packet was IP and TCP. */
+ #define RX_TPA_START_CMPL_FLAGS_ITYPE_TCP (UINT32_C(0x2) << 12)
+ #define RX_TPA_START_CMPL_FLAGS_ITYPE_LAST RX_TPA_START_CMPL_FLAGS_ITYPE_TCP
+ #define RX_TPA_START_CMPL_FLAGS_MASK UINT32_C(0xffc0)
+ #define RX_TPA_START_CMPL_FLAGS_SFT 6
+ uint16_t len;
+ /*
+ * This value indicates the amount of packet data written to the buffer
+ * the opaque field in this completion corresponds to.
+ */
+ uint32_t opaque;
+ /*
+ * This is a copy of the opaque field from the RX BD this completion
+ * corresponds to.
+ */
+ uint8_t v1;
+ /* unused1 is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define RX_TPA_START_CMPL_V1 UINT32_C(0x1)
+ /* unused1 is 7 b */
+ uint8_t rss_hash_type;
+ /*
+ * This is the RSS hash type for the packet. The value is packed
+ * {tuple_extrac_op[1:0],rss_profile_id[4:0],tuple_extrac_op[2]}.
+ */
+ uint16_t agg_id;
+ /*
+ * This is the aggregation ID that the completion is associated with.
+ * Use this number to correlate the TPA start completion with the TPA
+ * end completion.
+ */
+ /* unused2 is 9 b */
+ /*
+ * This is the aggregation ID that the completion is associated with.
+ * Use this number to correlate the TPA start completion with the TPA
+ * end completion.
+ */
+ #define RX_TPA_START_CMPL_AGG_ID_MASK UINT32_C(0xfe00)
+ #define RX_TPA_START_CMPL_AGG_ID_SFT 9
+ uint32_t rss_hash;
+ /*
+ * This value is the RSS hash value calculated for the packet based on
+ * the mode bits and key value in the VNIC.
+ */
+} __attribute__((packed));
+
+/* last 16 bytes of RX L2 TPA Start Completion Record */
+
+struct rx_tpa_start_cmpl_hi {
+ uint32_t flags2;
+ /*
+ * This indicates that the ip checksum was calculated for the inner
+ * packet and that the sum passed for all segments included in the
+ * aggregation.
+ */
+ #define RX_TPA_START_CMPL_FLAGS2_IP_CS_CALC UINT32_C(0x1)
+ /*
+ * This indicates that the TCP, UDP or ICMP checksum was calculated for
+ * the inner packet and that the sum passed for all segments included in
+ * the aggregation.
+ */
+ #define RX_TPA_START_CMPL_FLAGS2_L4_CS_CALC UINT32_C(0x2)
+ /*
+ * This indicates that the ip checksum was calculated for the tunnel
+ * header and that the sum passed for all segments included in the
+ * aggregation.
+ */
+ #define RX_TPA_START_CMPL_FLAGS2_T_IP_CS_CALC UINT32_C(0x4)
+ /*
+ * This indicates that the UDP checksum was calculated for the tunnel
+ * packet and that the sum passed for all segments included in the
+ * aggregation.
+ */
+ #define RX_TPA_START_CMPL_FLAGS2_T_L4_CS_CALC UINT32_C(0x8)
+ /* This value indicates what format the metadata field is. */
+ #define RX_TPA_START_CMPL_FLAGS2_META_FORMAT_MASK UINT32_C(0xf0)
+ #define RX_TPA_START_CMPL_FLAGS2_META_FORMAT_SFT 4
+ /* No metadata informtaion. Value is zero. */
+ #define RX_TPA_START_CMPL_FLAGS2_META_FORMAT_NONE (UINT32_C(0x0) << 4)
+ /*
+ * The metadata field contains the VLAN tag and TPID value. -
+ * metadata[11:0] contains the vlan VID value. - metadata[12]
+ * contains the vlan DE value. - metadata[15:13] contains the
+ * vlan PRI value. - metadata[31:16] contains the vlan TPID
+ * value.
+ */
+ #define RX_TPA_START_CMPL_FLAGS2_META_FORMAT_VLAN (UINT32_C(0x1) << 4)
+ #define RX_TPA_START_CMPL_FLAGS2_META_FORMAT_LAST RX_TPA_START_CMPL_FLAGS2_META_FORMAT_VLAN
+ /*
+ * This field indicates the IP type for the inner-most IP header. A
+ * value of '0' indicates IPv4. A value of '1' indicates IPv6.
+ */
+ #define RX_TPA_START_CMPL_FLAGS2_IP_TYPE UINT32_C(0x100)
+ uint32_t metadata;
+ /*
+ * This is data from the CFA block as indicated by the meta_format
+ * field.
+ */
+ /* When meta_format=1, this value is the VLAN VID. */
+ #define RX_TPA_START_CMPL_METADATA_VID_MASK UINT32_C(0xfff)
+ #define RX_TPA_START_CMPL_METADATA_VID_SFT 0
+ /* When meta_format=1, this value is the VLAN DE. */
+ #define RX_TPA_START_CMPL_METADATA_DE UINT32_C(0x1000)
+ /* When meta_format=1, this value is the VLAN PRI. */
+ #define RX_TPA_START_CMPL_METADATA_PRI_MASK UINT32_C(0xe000)
+ #define RX_TPA_START_CMPL_METADATA_PRI_SFT 13
+ /* When meta_format=1, this value is the VLAN TPID. */
+ #define RX_TPA_START_CMPL_METADATA_TPID_MASK UINT32_C(0xffff0000)
+ #define RX_TPA_START_CMPL_METADATA_TPID_SFT 16
+ uint16_t v2;
+ /* unused4 is 15 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define RX_TPA_START_CMPL_V2 UINT32_C(0x1)
+ /* unused4 is 15 b */
+ uint16_t cfa_code;
+ /*
+ * This field identifies the CFA action rule that was used for this
+ * packet.
+ */
+ uint32_t inner_l4_size_inner_l3_offset_inner_l2_offset_outer_l3_offset;
+ /*
+ * This is the size in bytes of the inner most L4 header. This can be
+ * subtracted from the payload_offset to determine the start of the
+ * inner most L4 header.
+ */
+ /*
+ * This is the offset from the beginning of the packet in bytes for the
+ * outer L3 header. If there is no outer L3 header, then this value is
+ * zero.
+ */
+ #define RX_TPA_START_CMPL_OUTER_L3_OFFSET_MASK UINT32_C(0x1ff)
+ #define RX_TPA_START_CMPL_OUTER_L3_OFFSET_SFT 0
+ /*
+ * This is the offset from the beginning of the packet in bytes for the
+ * inner most L2 header.
+ */
+ #define RX_TPA_START_CMPL_INNER_L2_OFFSET_MASK UINT32_C(0x3fe00)
+ #define RX_TPA_START_CMPL_INNER_L2_OFFSET_SFT 9
+ /*
+ * This is the offset from the beginning of the packet in bytes for the
+ * inner most L3 header.
+ */
+ #define RX_TPA_START_CMPL_INNER_L3_OFFSET_MASK UINT32_C(0x7fc0000)
+ #define RX_TPA_START_CMPL_INNER_L3_OFFSET_SFT 18
+ /*
+ * This is the size in bytes of the inner most L4 header. This can be
+ * subtracted from the payload_offset to determine the start of the
+ * inner most L4 header.
+ */
+ #define RX_TPA_START_CMPL_INNER_L4_SIZE_MASK UINT32_C(0xf8000000)
+ #define RX_TPA_START_CMPL_INNER_L4_SIZE_SFT 27
+} __attribute__((packed));
+
+/* RX TPA End Completion Record (32 bytes split to 2 16-byte struct) */
+
+struct rx_tpa_end_cmpl {
+ uint16_t flags_type;
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define RX_TPA_END_CMPL_TYPE_MASK UINT32_C(0x3f)
+ #define RX_TPA_END_CMPL_TYPE_SFT 0
+ /*
+ * RX L2 TPA End Completion: Completion at the end of a TPA
+ * operation. Length = 32B
+ */
+ #define RX_TPA_END_CMPL_TYPE_RX_TPA_END UINT32_C(0x15)
+ /*
+ * When this bit is '1', it indicates a packet that has an error of some
+ * type. Type of error is indicated in error_flags.
+ */
+ #define RX_TPA_END_CMPL_FLAGS_ERROR UINT32_C(0x40)
+ /* This field indicates how the packet was placed in the buffer. */
+ #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_MASK UINT32_C(0x380)
+ #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_SFT 7
+ /*
+ * Jumbo: TPA Packet was placed using jumbo algorithm. This
+ * means that the first buffer will be filled with data before
+ * moving to aggregation buffers. Each aggregation buffer will
+ * be filled before moving to the next aggregation buffer.
+ */
+ #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_JUMBO (UINT32_C(0x1) << 7)
+ /*
+ * Header/Data Separation: Packet was placed using Header/Data
+ * separation algorithm. The separation location is indicated by
+ * the itype field.
+ */
+ #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_HDS (UINT32_C(0x2) << 7)
+ /*
+ * GRO/Jumbo: Packet will be placed using GRO/Jumbo where the
+ * first packet is filled with data. Subsequent packets will be
+ * placed such that any one packet does not span two aggregation
+ * buffers unless it starts at the beginning of an aggregation
+ * buffer.
+ */
+ #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_GRO_JUMBO (UINT32_C(0x5) << 7)
+ /*
+ * GRO/Header-Data Separation: Packet will be placed using
+ * GRO/HDS where the header is in the first packet. Payload of
+ * each packet will be placed such that any one packet does not
+ * span two aggregation buffers unless it starts at the
+ * beginning of an aggregation buffer.
+ */
+ #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_GRO_HDS (UINT32_C(0x6) << 7)
+ #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_LAST RX_TPA_END_CMPL_FLAGS_PLACEMENT_GRO_HDS
+ /* unused is 2 b */
+ /*
+ * This value indicates what the inner packet determined for the packet
+ * was. - 2 TCP Packet Indicates that the packet was IP and TCP. This
+ * indicates that the ip_cs field is valid and that the tcp_udp_cs field
+ * is valid and contains the TCP checksum. This also indicates that the
+ * payload_offset field is valid.
+ */
+ #define RX_TPA_END_CMPL_FLAGS_ITYPE_MASK UINT32_C(0xf000)
+ #define RX_TPA_END_CMPL_FLAGS_ITYPE_SFT 12
+ #define RX_TPA_END_CMPL_FLAGS_MASK UINT32_C(0xffc0)
+ #define RX_TPA_END_CMPL_FLAGS_SFT 6
+ uint16_t len;
+ /*
+ * This value is zero for TPA End completions. There is no data in the
+ * buffer that corresponds to the opaque value in this completion.
+ */
+ uint32_t opaque;
+ /*
+ * This is a copy of the opaque field from the RX BD this completion
+ * corresponds to.
+ */
+ uint8_t agg_bufs_v1;
+ /* unused1 is 1 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define RX_TPA_END_CMPL_V1 UINT32_C(0x1)
+ /*
+ * This value is the number of aggregation buffers that follow this
+ * entry in the completion ring that are a part of this aggregation
+ * packet. If the value is zero, then the packet is completely contained
+ * in the buffer space provided in the aggregation start completion.
+ */
+ #define RX_TPA_END_CMPL_AGG_BUFS_MASK UINT32_C(0x7e)
+ #define RX_TPA_END_CMPL_AGG_BUFS_SFT 1
+ /* unused1 is 1 b */
+ uint8_t tpa_segs;
+ /* This value is the number of segments in the TPA operation. */
+ uint8_t payload_offset;
+ /*
+ * This value indicates the offset in bytes from the beginning of the
+ * packet where the inner payload starts. This value is valid for TCP,
+ * UDP, FCoE, and RoCE packets. A value of zero indicates an offset of
+ * 256 bytes.
+ */
+ uint8_t agg_id;
+ /*
+ * This is the aggregation ID that the completion is associated with.
+ * Use this number to correlate the TPA start completion with the TPA
+ * end completion.
+ */
+ /* unused2 is 1 b */
+ /*
+ * This is the aggregation ID that the completion is associated with.
+ * Use this number to correlate the TPA start completion with the TPA
+ * end completion.
+ */
+ #define RX_TPA_END_CMPL_AGG_ID_MASK UINT32_C(0xfe)
+ #define RX_TPA_END_CMPL_AGG_ID_SFT 1
+ uint32_t tsdelta;
+ /*
+ * For non-GRO packets, this value is the timestamp delta between
+ * earliest and latest timestamp values for TPA packet. If packets were
+ * not time stamped, then delta will be zero. For GRO packets, this
+ * field is zero except for the following sub-fields. - tsdelta[31]
+ * Timestamp present indication. When '0', no Timestamp option is in the
+ * packet. When '1', then a Timestamp option is present in the packet.
+ */
+} __attribute__((packed));
+
+/* last 16 bytes of RX TPA End Completion Record */
+
+struct rx_tpa_end_cmpl_hi {
+ uint32_t tpa_dup_acks;
+ /* unused3 is 28 b */
+ /*
+ * This value is the number of duplicate ACKs that have been received as
+ * part of the TPA operation.
+ */
+ #define RX_TPA_END_CMPL_TPA_DUP_ACKS_MASK UINT32_C(0xf)
+ #define RX_TPA_END_CMPL_TPA_DUP_ACKS_SFT 0
+ /* unused3 is 28 b */
+ uint16_t tpa_seg_len;
+ /*
+ * This value is the valid when TPA completion is active. It indicates
+ * the length of the longest segment of the TPA operation for LRO mode
+ * and the length of the first segment in GRO mode. This value may be
+ * used by GRO software to re-construct the original packet stream from
+ * the TPA packet. This is the length of all but the last segment for
+ * GRO. In LRO mode this value may be used to indicate MSS size to the
+ * stack.
+ */
+ uint16_t unused_3;
+ /* unused4 is 16 b */
+ uint16_t errors_v2;
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define RX_TPA_END_CMPL_V2 UINT32_C(0x1)
+ /*
+ * This error indicates that there was some sort of problem with the BDs
+ * for the packet that was found after part of the packet was already
+ * placed. The packet should be treated as invalid.
+ */
+ #define RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_MASK UINT32_C(0xe)
+ #define RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_SFT 1
+ /*
+ * This error occurs when there is a fatal HW problem in the
+ * chip only. It indicates that there were not BDs on chip but
+ * that there was adequate reservation. provided by the TPA
+ * block.
+ */
+ #define RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (UINT32_C(0x2) << 1)
+ /*
+ * This error occurs when TPA block was not configured to
+ * reserve adequate BDs for TPA operations on this RX ring. All
+ * data for the TPA operation was not placed. This error can
+ * also be generated when the number of segments is not
+ * programmed correctly in TPA and the 33 total aggregation
+ * buffers allowed for the TPA operation has been exceeded.
+ */
+ #define RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_RSV_ERROR (UINT32_C(0x4) << 1)
+ #define RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_LAST RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_RSV_ERROR
+ #define RX_TPA_END_CMPL_ERRORS_MASK UINT32_C(0xfffe)
+ #define RX_TPA_END_CMPL_ERRORS_SFT 1
+ uint16_t unused_4;
+ /* unused5 is 16 b */
+ uint32_t start_opaque;
+ /*
+ * This is the opaque value that was completed for the TPA start
+ * completion that corresponds to this TPA end completion.
+ */
+} __attribute__((packed));
+
+/* RX Aggregation Buffer Completion Record (16 bytes) */
+
+struct rx_abuf_cmpl {
+ uint16_t type;
+ /* unused is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define RX_ABUF_CMPL_TYPE_MASK UINT32_C(0x3f)
+ #define RX_ABUF_CMPL_TYPE_SFT 0
+ /*
+ * RX Aggregation Buffer completion : Completion of an L2
+ * aggregation buffer in support of TPA, HDS, or Jumbo packet
+ * completion. Length = 16B
+ */
+ #define RX_ABUF_CMPL_TYPE_RX_AGG UINT32_C(0x12)
+ /* unused is 10 b */
+ uint16_t len;
+ /*
+ * This is the length of the data for the packet stored in this
+ * aggregation buffer identified by the opaque value. This does not
+ * include the length of any data placed in other aggregation BDs or in
+ * the packet or buffer BDs. This length does not include any space
+ * added due to hdr_offset register during HDS placement mode.
+ */
+ uint32_t opaque;
+ /*
+ * This is a copy of the opaque field from the RX BD this aggregation
+ * buffer corresponds to.
+ */
+ uint32_t v;
+ /* unused2 is 31 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define RX_ABUF_CMPL_V UINT32_C(0x1)
+ /* unused2 is 31 b */
+ uint32_t unused_2;
+ /* unused3 is 32 b */
+} __attribute__((packed));
+
+/* Statistics Ejection Buffer Completion Record (16 bytes) */
+
+struct eject_cmpl {
+ uint16_t type;
+ /* unused is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define EJECT_CMPL_TYPE_MASK UINT32_C(0x3f)
+ #define EJECT_CMPL_TYPE_SFT 0
+ /*
+ * Statistics Ejection Completion: Completion of statistics data
+ * ejection buffer. Length = 16B
+ */
+ #define EJECT_CMPL_TYPE_STAT_EJECT UINT32_C(0x1a)
+ /* unused is 10 b */
+ uint16_t len;
+ /* This is the length of the statistics data stored in this buffer. */
+ uint32_t opaque;
+ /*
+ * This is a copy of the opaque field from the RX BD this ejection
+ * buffer corresponds to.
+ */
+ uint32_t v;
+ /* unused2 is 31 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define EJECT_CMPL_V UINT32_C(0x1)
+ /* unused2 is 31 b */
+ uint32_t unused_2;
+ /* unused3 is 32 b */
+} __attribute__((packed));
+
+/* HWRM Completion Record (16 bytes) */
+
+struct hwrm_cmpl {
+ uint16_t type;
+ /* unused is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_CMPL_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_CMPL_TYPE_SFT 0
+ /* HWRM Command Completion: Completion of an HWRM command. */
+ #define HWRM_CMPL_TYPE_HWRM_DONE UINT32_C(0x20)
+ /* unused is 10 b */
+ uint16_t sequence_id;
+ /* This is the sequence_id of the HWRM command that has completed. */
+ uint32_t unused_1;
+ /* unused2 is 32 b */
+ uint32_t v;
+ /* unused3 is 31 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_CMPL_V UINT32_C(0x1)
+ /* unused3 is 31 b */
+ uint32_t unused_3;
+ /* unused4 is 32 b */
+} __attribute__((packed));
+
+/* HWRM Forwarded Request (16 bytes) */
+
+struct hwrm_fwd_req_cmpl {
+ uint16_t req_len_type;
+ /* Length of forwarded request in bytes. */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_FWD_REQ_CMPL_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_FWD_REQ_CMPL_TYPE_SFT 0
+ /* Forwarded HWRM Request */
+ #define HWRM_FWD_REQ_CMPL_TYPE_HWRM_FWD_REQ UINT32_C(0x22)
+ /* Length of forwarded request in bytes. */
+ #define HWRM_FWD_REQ_CMPL_REQ_LEN_MASK UINT32_C(0xffc0)
+ #define HWRM_FWD_REQ_CMPL_REQ_LEN_SFT 6
+ uint16_t source_id;
+ /*
+ * Source ID of this request. Typically used in forwarding requests and
+ * responses. 0x0 - 0xFFF8 - Used for function ids 0xFFF8 - 0xFFFE -
+ * Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint32_t unused_0;
+ /* unused1 is 32 b */
+ uint64_t req_buf_addr_v;
+ /* Address of forwarded request. */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_FWD_REQ_CMPL_V UINT32_C(0x1)
+ /* Address of forwarded request. */
+ #define HWRM_FWD_REQ_CMPL_REQ_BUF_ADDR_MASK UINT32_C(0xfffffffe)
+ #define HWRM_FWD_REQ_CMPL_REQ_BUF_ADDR_SFT 1
+} __attribute__((packed));
+
+/* HWRM Forwarded Response (16 bytes) */
+
+struct hwrm_fwd_resp_cmpl {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_FWD_RESP_CMPL_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_FWD_RESP_CMPL_TYPE_SFT 0
+ /* Forwarded HWRM Response */
+ #define HWRM_FWD_RESP_CMPL_TYPE_HWRM_FWD_RESP UINT32_C(0x24)
+ /* unused1 is 10 b */
+ uint16_t source_id;
+ /*
+ * Source ID of this response. Typically used in forwarding requests and
+ * responses. 0x0 - 0xFFF8 - Used for function ids 0xFFF8 - 0xFFFE -
+ * Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint16_t resp_len;
+ /* Length of forwarded response in bytes. */
+ uint16_t unused_1;
+ /* unused2 is 16 b */
+ uint64_t resp_buf_addr_v;
+ /* Address of forwarded response. */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_FWD_RESP_CMPL_V UINT32_C(0x1)
+ /* Address of forwarded response. */
+ #define HWRM_FWD_RESP_CMPL_RESP_BUF_ADDR_MASK UINT32_C(0xfffffffe)
+ #define HWRM_FWD_RESP_CMPL_RESP_BUF_ADDR_SFT 1
+} __attribute__((packed));
+
+#define GET_EVENT_ID(x) \
+ ((x) == 0x30 ? "VF_FLR": \
+ ((x) == 0x20 ? "PF_DRVR_UNLOAD": \
+ ((x) == 0x10 ? "FUNC_DRVR_UNLOAD": \
+ ((x) == 0xff ? "HWRM_ERROR": \
+ ((x) == 0x32 ? "PF_VF_COMM_STATUS_CHANGE": \
+ ((x) == 0x33 ? "VF_CFG_CHANGE": \
+ ((x) == 0x11 ? "FUNC_DRVR_LOAD": \
+ ((x) == 0x31 ? "VF_MAC_ADDR_CHANGE": \
+ ((x) == 0x4 ? "PORT_CONN_NOT_ALLOWED": \
+ ((x) == 0x5 ? "LINK_SPEED_CFG_NOT_ALLOWED": \
+ ((x) == 0x6 ? "LINK_SPEED_CFG_CHANGE": \
+ ((x) == 0x7 ? "PORT_PHY_CFG_CHANGE": \
+ ((x) == 0x0 ? "LINK_STATUS_CHANGE": \
+ ((x) == 0x1 ? "LINK_MTU_CHANGE": \
+ ((x) == 0x2 ? "LINK_SPEED_CHANGE": \
+ ((x) == 0x3 ? "DCB_CONFIG_CHANGE": \
+ ((x) == 0x12 ? "FUNC_FLR_PROC_CMPLT": \
+ ((x) == 0x21 ? "PF_DRVR_LOAD": \
+ "Unknown event_id"))))))))))))))))))
+
+/* HWRM Asynchronous Event Completion Record (16 bytes) */
+
+struct hwrm_async_event_cmpl {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Link status changed */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE UINT32_C(0x0)
+ /* Link MTU changed */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE UINT32_C(0x1)
+ /* Link speed changed */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE UINT32_C(0x2)
+ /* DCB Configuration changed */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE UINT32_C(0x3)
+ /* Port connection not allowed */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED UINT32_C(0x4)
+ /* Link speed configuration was not allowed */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED UINT32_C(0x5)
+ /* Link speed configuration change */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE UINT32_C(0x6)
+ /* Port PHY configuration change */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE UINT32_C(0x7)
+ /* Function driver unloaded */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD UINT32_C(0x10)
+ /* Function driver loaded */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD UINT32_C(0x11)
+ /* Function FLR related processing has completed */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_FLR_PROC_CMPLT UINT32_C(0x12)
+ /* PF driver unloaded */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD UINT32_C(0x20)
+ /* PF driver loaded */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD UINT32_C(0x21)
+ /* VF Function Level Reset (FLR) */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR UINT32_C(0x30)
+ /* VF MAC Address Change */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE UINT32_C(0x31)
+ /* PF-VF communication channel status change. */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE UINT32_C(0x32)
+ /* VF Configuration Change */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE UINT32_C(0x33)
+ /* HWRM Error */
+ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR UINT32_C(0xff)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for link status change (16 bytes) */
+
+struct hwrm_async_event_cmpl_link_status_change {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Link status changed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_ID_LINK_STATUS_CHANGE UINT32_C(0x0)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* Indicates link status change */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE UINT32_C(0x1)
+ /*
+ * If this bit set to 0, then it indicates that the link was up
+ * and it went down.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_DOWN (UINT32_C(0x0) << 0)
+ /*
+ * If this bit is set to 1, then it indicates that the link was
+ * down and it went up.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP (UINT32_C(0x1) << 0)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_LAST HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP
+ /* Indicates the physical port this link status change occur */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_MASK UINT32_C(0xe)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_SFT 1
+ /* PORT ID */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff0)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_SFT 4
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for link MTU change (16 bytes) */
+
+struct hwrm_async_event_cmpl_link_mtu_change {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Link MTU changed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_ID_LINK_MTU_CHANGE UINT32_C(0x1)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* The new MTU of the link in bytes. */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_SFT 0
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for link speed change (16 bytes) */
+
+struct hwrm_async_event_cmpl_link_speed_change {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Link speed changed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_ID_LINK_SPEED_CHANGE UINT32_C(0x2)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /*
+ * When this bit is '1', the link was forced to the force_link_speed
+ * value.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_FORCE UINT32_C(0x1)
+ /* The new link speed in 100 Mbps units. */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_MASK UINT32_C(0xfffe)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_SFT 1
+ /* 100Mb link speed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100MB (UINT32_C(0x1) << 1)
+ /* 1Gb link speed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_1GB (UINT32_C(0xa) << 1)
+ /* 2Gb link speed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2GB (UINT32_C(0x14) << 1)
+ /* 2.5Gb link speed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2_5GB (UINT32_C(0x19) << 1)
+ /* 10Gb link speed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_10GB (UINT32_C(0x64) << 1)
+ /* 20Mb link speed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_20GB (UINT32_C(0xc8) << 1)
+ /* 25Gb link speed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_25GB (UINT32_C(0xfa) << 1)
+ /* 40Gb link speed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_40GB (UINT32_C(0x190) << 1)
+ /* 50Gb link speed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_50GB (UINT32_C(0x1f4) << 1)
+ /* 100Gb link speed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB (UINT32_C(0x3e8) << 1)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_LAST HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB
+ /* PORT ID */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff0000)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_SFT 16
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for DCB Config change (16 bytes) */
+
+struct hwrm_async_event_cmpl_dcb_config_change {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* DCB Configuration changed */
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_ID_DCB_CONFIG_CHANGE UINT32_C(0x3)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* PORT ID */
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for port connection not allowed (16 bytes) */
+
+struct hwrm_async_event_cmpl_port_conn_not_allowed {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Port connection not allowed */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_ID_PORT_CONN_NOT_ALLOWED UINT32_C(0x4)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* PORT ID */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0
+ /*
+ * This value indicates the current port level enforcement policy for
+ * the optics module when there is an optical module mismatch and port
+ * is not connected.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_MASK UINT32_C(0xff0000)
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_SFT 16
+ /* No enforcement */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_NONE (UINT32_C(0x0) << 16)
+ /* Disable Transmit side Laser. */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_DISABLETX (UINT32_C(0x1) << 16)
+ /* Raise a warning message. */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_WARNINGMSG (UINT32_C(0x2) << 16)
+ /* Power down the module. */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN (UINT32_C(0x3) << 16)
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_LAST HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for link speed config not allowed (16 bytes) */
+
+struct hwrm_async_event_cmpl_link_speed_cfg_not_allowed {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Link speed configuration was not allowed */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED UINT32_C(0x5)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* PORT ID */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for link speed configuration change (16 bytes) */
+
+struct hwrm_async_event_cmpl_link_speed_cfg_change {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Link speed configuration change */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_ID_LINK_SPEED_CFG_CHANGE UINT32_C(0x6)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* PORT ID */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
+ /*
+ * If set to 1, it indicates that the supported link speeds
+ * configuration on the port has changed. If set to 0, then there is no
+ * change in supported link speeds configuration.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_SUPPORTED_LINK_SPEEDS_CHANGE UINT32_C(0x10000)
+ /*
+ * If set to 1, it indicates that the link speed configuration on the
+ * port has become illegal or invalid. If set to 0, then the link speed
+ * configuration on the port is legal or valid.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_ILLEGAL_LINK_SPEED_CFG UINT32_C(0x20000)
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for port PHY configuration change (16 bytes) */
+
+struct hwrm_async_event_cmpl_port_phy_cfg_change {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Port PHY configuration change */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_ID_PORT_PHY_CFG_CHANGE UINT32_C(0x7)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* PORT ID */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
+ /*
+ * If set to 1, it indicates that the FEC configuration on the port has
+ * changed. If set to 0, then there is no change in FEC configuration.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA1_FEC_CFG_CHANGE UINT32_C(0x10000)
+ /*
+ * If set to 1, it indicates that the EEE configuration on the port has
+ * changed. If set to 0, then there is no change in EEE configuration on
+ * the port.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA1_EEE_CFG_CHANGE UINT32_C(0x20000)
+ /*
+ * If set to 1, it indicates that the pause configuration on the PHY has
+ * changed. If set to 0, then there is no change in the pause
+ * configuration on the PHY.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA1_PAUSE_CFG_CHANGE UINT32_C(0x40000)
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for Function Driver Unload (16 bytes) */
+
+struct hwrm_async_event_cmpl_func_drvr_unload {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Function driver unloaded */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_ID_FUNC_DRVR_UNLOAD UINT32_C(0x10)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* Function ID */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for Function Driver load (16 bytes) */
+
+struct hwrm_async_event_cmpl_func_drvr_load {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Function driver loaded */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_ID_FUNC_DRVR_LOAD UINT32_C(0x11)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* Function ID */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record to indicate completion of FLR related processing (16 bytes) */
+
+struct hwrm_async_event_cmpl_func_flr_proc_cmplt {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* Function FLR related processing has completed */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_ID_FUNC_FLR_PROC_CMPLT UINT32_C(0x12)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* Function ID */
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_DATA1_FUNC_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_DATA1_FUNC_ID_SFT 0
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for PF Driver Unload (16 bytes) */
+
+struct hwrm_async_event_cmpl_pf_drvr_unload {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* PF driver unloaded */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_ID_PF_DRVR_UNLOAD UINT32_C(0x20)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* PF ID */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0
+ /* Indicates the physical port this pf belongs to */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_MASK UINT32_C(0x70000)
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_SFT 16
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for PF Driver load (16 bytes) */
+
+struct hwrm_async_event_cmpl_pf_drvr_load {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* PF driver loaded */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_ID_PF_DRVR_LOAD UINT32_C(0x21)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* PF ID */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0
+ /* Indicates the physical port this pf belongs to */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_MASK UINT32_C(0x70000)
+ #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_SFT 16
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for VF FLR (16 bytes) */
+
+struct hwrm_async_event_cmpl_vf_flr {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* VF Function Level Reset (FLR) */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_ID_VF_FLR UINT32_C(0x30)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* VF ID */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_SFT 0
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for VF MAC Addr change (16 bytes) */
+
+struct hwrm_async_event_cmpl_vf_mac_addr_change {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* VF MAC Address Change */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_ID_VF_MAC_ADDR_CHANGE UINT32_C(0x31)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* VF ID */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_MASK UINT32_C(0xffff)
+ #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_SFT 0
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for PF-VF communication status change (16 bytes) */
+
+struct hwrm_async_event_cmpl_pf_vf_comm_status_change {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* PF-VF communication channel status change. */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_ID_PF_VF_COMM_STATUS_CHANGE UINT32_C(0x32)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /*
+ * If this bit is set to 1, then it indicates that the PF-VF
+ * communication was lost and it is established. If this bit set to 0,
+ * then it indicates that the PF-VF communication was established and it
+ * is lost.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_DATA1_COMM_ESTABLISHED UINT32_C(0x1)
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for VF configuration change (16 bytes) */
+
+struct hwrm_async_event_cmpl_vf_cfg_change {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* VF Configuration Change */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_ID_VF_CFG_CHANGE UINT32_C(0x33)
+ uint32_t event_data2;
+ /* Event specific data */
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /*
+ * Each flag provided in this field indicates a specific VF
+ * configuration change. At least one of these flags shall be set to 1
+ * when an asynchronous event completion of this type is provided by the
+ * HWRM.
+ */
+ /*
+ * If this bit is set to 1, then the value of MTU was changed on this
+ * VF. If set to 0, then this bit should be ignored.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MTU_CHANGE UINT32_C(0x1)
+ /*
+ * If this bit is set to 1, then the value of MRU was changed on this
+ * VF. If set to 0, then this bit should be ignored.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MRU_CHANGE UINT32_C(0x2)
+ /*
+ * If this bit is set to 1, then the value of default MAC address was
+ * changed on this VF. If set to 0, then this bit should be ignored.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_MAC_ADDR_CHANGE UINT32_C(0x4)
+ /*
+ * If this bit is set to 1, then the value of default VLAN was changed
+ * on this VF. If set to 0, then this bit should be ignored.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_VLAN_CHANGE UINT32_C(0x8)
+} __attribute__((packed));
+
+/* HWRM Asynchronous Event Completion Record for HWRM Error (16 bytes) */
+
+struct hwrm_async_event_cmpl_hwrm_error {
+ uint16_t type;
+ /* unused1 is 10 b */
+ /*
+ * This field indicates the exact type of the completion. By convention,
+ * the LSB identifies the length of the record in 16B units. Even values
+ * indicate 16B records. Odd values indicate 32B records.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_MASK UINT32_C(0x3f)
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_SFT 0
+ /* HWRM Asynchronous Event Information */
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e)
+ /* unused1 is 10 b */
+ uint16_t event_id;
+ /* Identifiers of events. */
+ /* HWRM Error */
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_ID_HWRM_ERROR UINT32_C(0xff)
+ uint32_t event_data2;
+ /* Event specific data */
+ /* Severity of HWRM Error */
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_MASK UINT32_C(0xff)
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_SFT 0
+ /* Warning */
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_WARNING UINT32_C(0x0)
+ /* Non-fatal Error */
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_NONFATAL UINT32_C(0x1)
+ /* Fatal Error */
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL UINT32_C(0x2)
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_LAST HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL
+ uint8_t opaque_v;
+ /* opaque is 7 b */
+ /*
+ * This value is written by the NIC such that it will be different for
+ * each pass through the completion queue. The even passes will write 1.
+ * The odd passes will write 0.
+ */
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_V UINT32_C(0x1)
+ /* opaque is 7 b */
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_MASK UINT32_C(0xfe)
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_SFT 1
+ uint8_t timestamp_lo;
+ /* 8-lsb timestamp from POR (100-msec resolution) */
+ uint16_t timestamp_hi;
+ /* 16-lsb timestamp from POR (100-msec resolution) */
+ uint32_t event_data1;
+ /* Event specific data */
+ /* Time stamp for error event */
+ #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA1_TIMESTAMP UINT32_C(0x1)
+} __attribute__((packed));
+
+/* Door Bell Formats */
+/*
+ * Description: The backup version of the packet must be valid in the TX ring
+ * before the push doorbell is written to the chip. The first 32b and the BD
+ * portion of the push doorbell must be written in multiples of 32b units on the
+ * PCI interface. The data portion of the push doorbell may be written in
+ * multiples of 8b units on the PCI interface. A push update must contain
+ * exactly one push packet. The backup version of the packet must start with a
+ * long (32B) BD and the BDs must be less than or equal to 16x16B units long.
+ */
+/*
+ * Note: This door bell format is used by the driver when it wants to push a
+ * packet into the chip for super-fast transmission. This pushes a partial BD
+ * and the packet data into the chip. If the chip has room, it will transmit the
+ * packet. If the chip dosn't have room, it will read the BD and packet data
+ * from host memory as a normal packet.
+ */
+/* TX Door Bell Format (4 bytes) */
+
+struct tx_doorbell {
+ uint32_t key_idx;
+ /*
+ * This value indicates the type of door bell operation that is begin
+ * requested. This value is '0' for TX door bell operations.
+ */
+ /*
+ * BD Index of next BD that will be used to transmit data on the TX ring
+ * mapped to this door bell. NIC may read and process all BDs up to, but
+ * not including this index.
+ */
+ #define TX_DOORBELL_IDX_MASK UINT32_C(0xffffff)
+ #define TX_DOORBELL_IDX_SFT 0
+ /* reserved is 4 b */
+ #define TX_DOORBELL_RESERVED_MASK UINT32_C(0xf000000)
+ #define TX_DOORBELL_RESERVED_SFT 24
+ /*
+ * This value indicates the type of door bell operation that is begin
+ * requested. This value is '0' for TX door bell operations.
+ */
+ #define TX_DOORBELL_KEY_MASK UINT32_C(0xf0000000)
+ #define TX_DOORBELL_KEY_SFT 28
+ /* TX Operation */
+ #define TX_DOORBELL_KEY_TX (UINT32_C(0x0) << 28)
+} __attribute__((packed));
+
+/* RX Door Bell Format (4 bytes) */
+
+struct rx_doorbell {
+ uint32_t key_idx;
+ /*
+ * This value indicates the type of door bell operation that is begin
+ * requested. This value is '1' for RX door bell operations.
+ */
+ /*
+ * BD Index of next BD that will be used for an empty receive buffer on
+ * the RX ring mapped to this door bell. NIC may read and process all
+ * BDs up to, but not including this index.
+ */
+ #define RX_DOORBELL_IDX_MASK UINT32_C(0xffffff)
+ #define RX_DOORBELL_IDX_SFT 0
+ /* reserved is 4 b */
+ #define RX_DOORBELL_RESERVED_MASK UINT32_C(0xf000000)
+ #define RX_DOORBELL_RESERVED_SFT 24
+ /*
+ * This value indicates the type of door bell operation that is begin
+ * requested. This value is '1' for RX door bell operations.
+ */
+ #define RX_DOORBELL_KEY_MASK UINT32_C(0xf0000000)
+ #define RX_DOORBELL_KEY_SFT 28
+ /* RX Operation */
+ #define RX_DOORBELL_KEY_RX (UINT32_C(0x1) << 28)
+} __attribute__((packed));
+
+/* CMP Door Bell Format (4 bytes) */
+
+struct cmpl_doorbell {
+ uint32_t key_mask_valid_idx;
+ /*
+ * This value indicates the type of door bell operation that is begin
+ * requested. This value is '2' for CMP door bell operations.
+ */
+ /*
+ * BD Index of the most recently handed completion record on the
+ * completion ring mapped to this door bell. NIC may write this location
+ * again with a new completion.
+ */
+ #define CMPL_DOORBELL_IDX_MASK UINT32_C(0xffffff)
+ #define CMPL_DOORBELL_IDX_SFT 0
+ /* reserved is 2 b */
+ #define CMPL_DOORBELL_RESERVED_MASK UINT32_C(0x3000000)
+ #define CMPL_DOORBELL_RESERVED_SFT 24
+ /*
+ * This indicates if the BDIDX value is valid for this update when it is
+ * '1'. When it is '0', the BDIDX value should be ignored.
+ */
+ #define CMPL_DOORBELL_IDX_VALID UINT32_C(0x4000000)
+ /*
+ * This bit indicates the new interrupt mask state for the interrupt
+ * associated with the BDIDX. A '1', means the interrupt is to be
+ * masked. A '0' indicates the interrupt is to be unmasked.
+ */
+ #define CMPL_DOORBELL_MASK UINT32_C(0x8000000)
+ /*
+ * This value indicates the type of door bell operation that is begin
+ * requested. This value is '2' for CMP door bell operations.
+ */
+ #define CMPL_DOORBELL_KEY_MASK UINT32_C(0xf0000000)
+ #define CMPL_DOORBELL_KEY_SFT 28
+ /* Completion Operation */
+ #define CMPL_DOORBELL_KEY_CMPL (UINT32_C(0x2) << 28)
+} __attribute__((packed));
+
+/* Status Door Bell Format (4 bytes) */
+
+struct status_doorbell {
+ uint32_t key_idx;
+ /*
+ * This value indicates the type of door bell operation that is begin
+ * requested. This value is '3' for Status door bell operations.
+ */
+ /*
+ * BD Index of the status record for which space is now available to the
+ * NIC.
+ */
+ /*
+ * While there is no actual BD associated with the index, the similar
+ * scheme is being used to communicate to the NIC that space is
+ * available for status completions.
+ */
+ #define STATUS_DOORBELL_IDX_MASK UINT32_C(0xffffff)
+ #define STATUS_DOORBELL_IDX_SFT 0
+ /* reserved is 4 b */
+ #define STATUS_DOORBELL_RESERVED_MASK UINT32_C(0xf000000)
+ #define STATUS_DOORBELL_RESERVED_SFT 24
+ /*
+ * This value indicates the type of door bell operation that is begin
+ * requested. This value is '3' for Status door bell operations.
+ */
+ #define STATUS_DOORBELL_KEY_MASK UINT32_C(0xf0000000)
+ #define STATUS_DOORBELL_KEY_SFT 28
+ /* Status Operation */
+ #define STATUS_DOORBELL_KEY_STAT (UINT32_C(0x3) << 28)
+} __attribute__((packed));
+
+/* Push w/32B BD Door Bell Format (32 bytes) */
+
+struct push32_doorbell {
+ uint32_t key_sz_idx;
+ /*
+ * This value indicates the type of door bell operation that is begin
+ * requested. This value is 4 for push door bell operations.
+ */
+ /*
+ * This is the BD Index of last BD of the push packet that will be used
+ * to transmit data on the TX ring mapped to this door bell.
+ */
+ #define PUSH32_DOORBELL_IDX_MASK UINT32_C(0xffffff)
+ #define PUSH32_DOORBELL_IDX_SFT 0
+ /*
+ * This is the number of 16B BDs spaces consumed in the TX Ring by the
+ * "backup" version of the packet being pushed. A value of 1 is invalid
+ * since backup must start with a long 32B BE. A value of 2 indicates
+ * just the first 32B BE. A value of 3 indicates 32B+16B BD. etc. A
+ * value of 0 indicates 16x16B BD spaces are consumed.
+ */
+ #define PUSH32_DOORBELL_SZ_MASK UINT32_C(0xf000000)
+ #define PUSH32_DOORBELL_SZ_SFT 24
+ /*
+ * This value indicates the type of door bell operation that is begin
+ * requested. This value is 4 for push door bell operations.
+ */
+ #define PUSH32_DOORBELL_KEY_MASK UINT32_C(0xf0000000)
+ #define PUSH32_DOORBELL_KEY_SFT 28
+ /* Push Operation */
+ #define PUSH32_DOORBELL_KEY_PUSH (UINT32_C(0x4) << 28)
+ uint16_t flags_type;
+ /*
+ * All bits in this field must be valid on the first BD of a packet.
+ * Only the packet_end bit must be valid for the remaining BDs of a
+ * packet.
+ */
+ /* This value identifies the type of buffer descriptor. */
+ #define PUSH32_DOORBELL_TYPE_MASK UINT32_C(0x3f)
+ #define PUSH32_DOORBELL_TYPE_SFT 0
+ /*
+ * Indicates that this BD is 32B long and is used for normal L2
+ * packet transmission.
+ */
+ #define PUSH32_DOORBELL_TYPE_TX_BD_LONG UINT32_C(0x10)
+ /*
+ * If set to 1, the packet ends with the data in the buffer pointed to
+ * by this descriptor. This flag must be valid on every BD. This bit
+ * must be set on all push doorbells.
+ */
+ #define PUSH32_DOORBELL_FLAGS_PACKET_END UINT32_C(0x40)
+ /*
+ * If set to 1, the device will not generate a completion for this
+ * transmit packet unless there is an error in it's processing. If this
+ * bit is set to 0, then the packet will be completed normally. This bit
+ * must be valid only on the first BD of a packet.
+ */
+ #define PUSH32_DOORBELL_FLAGS_NO_CMPL UINT32_C(0x80)
+ /*
+ * This value must match the sz field in the first 32b of the push
+ * operation except that if 16x16B BD locations are consumed in the ring
+ * by this packet, then this value must be 16 (not zero).
+ */
+ #define PUSH32_DOORBELL_FLAGS_BD_CNT_MASK UINT32_C(0x1f00)
+ #define PUSH32_DOORBELL_FLAGS_BD_CNT_SFT 8
+ /*
+ * This value is a hint for the length of the entire packet. It is used
+ * by the chip to optimize internal processing. The packet will be
+ * dropped if the hint is too short. This field is valid only on the
+ * first BD of a packet.
+ */
+ #define PUSH32_DOORBELL_FLAGS_LHINT_MASK UINT32_C(0x6000)
+ #define PUSH32_DOORBELL_FLAGS_LHINT_SFT 13
+ /* indicates packet length < 512B */
+ #define PUSH32_DOORBELL_FLAGS_LHINT_LT512 (UINT32_C(0x0) << 13)
+ /* indicates 512 <= packet length < 1KB */
+ #define PUSH32_DOORBELL_FLAGS_LHINT_LT1K (UINT32_C(0x1) << 13)
+ /* indicates 1KB <= packet length < 2KB */
+ #define PUSH32_DOORBELL_FLAGS_LHINT_LT2K (UINT32_C(0x2) << 13)
+ /* indicates packet length >= 2KB */
+ #define PUSH32_DOORBELL_FLAGS_LHINT_GTE2K (UINT32_C(0x3) << 13)
+ #define PUSH32_DOORBELL_FLAGS_LHINT_LAST PUSH32_DOORBELL_FLAGS_LHINT_GTE2K
+ /*
+ * If set to 1, the device immediately updates the Send Consumer Index
+ * after the buffer associated with this descriptor has been transferred
+ * via DMA to NIC memory from host memory. An interrupt may or may not
+ * be generated according to the state of the interrupt avoidance
+ * mechanisms. If this bit is set to 0, then the Consumer Index is only
+ * updated as soon as one of the host interrupt coalescing conditions
+ * has been met. This bit must be valid on the first BD of a packet.
+ */
+ #define PUSH32_DOORBELL_FLAGS_COAL_NOW UINT32_C(0x8000)
+ /*
+ * All bits in this field must be valid on the first BD of a packet.
+ * Only the packet_end bit must be valid for the remaining BDs of a
+ * packet.
+ */
+ #define PUSH32_DOORBELL_FLAGS_MASK UINT32_C(0xffc0)
+ #define PUSH32_DOORBELL_FLAGS_SFT 6
+ uint16_t len;
+ /*
+ * This is the length of the host physical buffer this BD describes in
+ * bytes. This field must be valid on all BDs of a packet.
+ */
+ uint32_t opaque;
+ /*
+ * The opaque data field is pass through to the completion and can be
+ * used for any data that the driver wants to associate with the
+ * transmit BD. This field must be valid on the first BD of a packet.
+ */
+ uint16_t lflags;
+ /*
+ * All bits in this field must be valid on the first BD of a packet.
+ * Their value on other BDs of the packet will be ignored.
+ */
+ /*
+ * If set to 1, the controller replaces the TCP/UPD checksum fields of
+ * normal TCP/UPD checksum, or the inner TCP/UDP checksum field of the
+ * encapsulated TCP/UDP packets with the hardware calculated TCP/UDP
+ * checksum for the packet associated with this descriptor. The flag is
+ * ignored if the LSO flag is set. This bit must be valid on the first
+ * BD of a packet.
+ */
+ #define PUSH32_DOORBELL_LFLAGS_TCP_UDP_CHKSUM UINT32_C(0x1)
+ /*
+ * If set to 1, the controller replaces the IP checksum of the normal
+ * packets, or the inner IP checksum of the encapsulated packets with
+ * the hardware calculated IP checksum for the packet associated with
+ * this descriptor. This bit must be valid on the first BD of a packet.
+ */
+ #define PUSH32_DOORBELL_LFLAGS_IP_CHKSUM UINT32_C(0x2)
+ /*
+ * If set to 1, the controller will not append an Ethernet CRC to the
+ * end of the frame. This bit must be valid on the first BD of a packet.
+ * Packet must be 64B or longer when this flag is set. It is not useful
+ * to use this bit with any form of TX offload such as CSO or LSO. The
+ * intent is that the packet from the host already has a valid Ethernet
+ * CRC on the packet.
+ */
+ #define PUSH32_DOORBELL_LFLAGS_NOCRC UINT32_C(0x4)
+ /*
+ * If set to 1, the device will record the time at which the packet was
+ * actually transmitted at the TX MAC. This bit must be valid on the
+ * first BD of a packet.
+ */
+ #define PUSH32_DOORBELL_LFLAGS_STAMP UINT32_C(0x8)
+ /*
+ * If set to 1, The controller replaces the tunnel IP checksum field
+ * with hardware calculated IP checksum for the IP header of the packet
+ * associated with this descriptor. For outer UDP checksum, global outer
+ * UDP checksum TE_NIC register needs to be enabled. If the global outer
+ * UDP checksum TE_NIC register bit is set, outer UDP checksum will be
+ * calculated for the following cases: 1. Packets with tcp_udp_chksum
+ * flag set to offload checksum for inner packet AND the inner packet is
+ * TCP/UDP. If the inner packet is ICMP for example (non-TCP/UDP), even
+ * if the tcp_udp_chksum is set, the outer UDP checksum will not be
+ * calculated. 2. Packets with lso flag set which implies inner TCP
+ * checksum calculation as part of LSO operation.
+ */
+ #define PUSH32_DOORBELL_LFLAGS_T_IP_CHKSUM UINT32_C(0x10)
+ /*
+ * If set to 1, the device will treat this packet with LSO(Large Send
+ * Offload) processing for both normal or encapsulated packets, which is
+ * a form of TCP segmentation. When this bit is 1, the hdr_size and mss
+ * fields must be valid. The driver doesn't need to set t_ip_chksum,
+ * ip_chksum, and tcp_udp_chksum flags since the controller will replace
+ * the appropriate checksum fields for segmented packets. When this bit
+ * is 1, the hdr_size and mss fields must be valid.
+ */
+ #define PUSH32_DOORBELL_LFLAGS_LSO UINT32_C(0x20)
+ /*
+ * If set to zero when LSO is '1', then the IPID will be treated as a
+ * 16b number and will be wrapped if it exceeds a value of 0xffff. If
+ * set to one when LSO is '1', then the IPID will be treated as a 15b
+ * number and will be wrapped if it exceeds a value 0f 0x7fff.
+ */
+ #define PUSH32_DOORBELL_LFLAGS_IPID_FMT UINT32_C(0x40)
+ /*
+ * If set to zero when LSO is '1', then the IPID of the tunnel IP header
+ * will not be modified during LSO operations. If set to one when LSO is
+ * '1', then the IPID of the tunnel IP header will be incremented for
+ * each subsequent segment of an LSO operation. The flag is ignored if
+ * the LSO packet is a normal (non-tunneled) TCP packet.
+ */
+ #define PUSH32_DOORBELL_LFLAGS_T_IPID UINT32_C(0x80)
+ /*
+ * If set to '1', then the RoCE ICRC will be appended to the packet.
+ * Packet must be a valid RoCE format packet.
+ */
+ #define PUSH32_DOORBELL_LFLAGS_ROCE_CRC UINT32_C(0x100)
+ /*
+ * If set to '1', then the FCoE CRC will be appended to the packet.
+ * Packet must be a valid FCoE format packet.
+ */
+ #define PUSH32_DOORBELL_LFLAGS_FCOE_CRC UINT32_C(0x200)
+ uint16_t hdr_size;
+ /*
+ * When LSO is '1', this field must contain the offset of the TCP
+ * payload from the beginning of the packet in as 16b words. In case of
+ * encapsulated/tunneling packet, this field contains the offset of the
+ * inner TCP payload from beginning of the packet as 16-bit words. This
+ * value must be valid on the first BD of a packet.
+ */
+ #define PUSH32_DOORBELL_HDR_SIZE_MASK UINT32_C(0x1ff)
+ #define PUSH32_DOORBELL_HDR_SIZE_SFT 0
+ uint32_t mss;
+ /*
+ * This is the MSS value that will be used to do the LSO processing. The
+ * value is the length in bytes of the TCP payload for each segment
+ * generated by the LSO operation. This value must be valid on the first
+ * BD of a packet.
+ */
+ #define PUSH32_DOORBELL_MSS_MASK UINT32_C(0x7fff)
+ #define PUSH32_DOORBELL_MSS_SFT 0
+ uint16_t unused_2;
+ uint16_t cfa_action;
+ /*
+ * This value selects a CFA action to perform on the packet. Set this
+ * value to zero if no CFA action is desired. This value must be valid
+ * on the first BD of a packet.
+ */
+ uint32_t cfa_meta;
+ /*
+ * This value is action meta-data that defines CFA edit operations that
+ * are done in addition to any action editing.
+ */
+ /* When key=1, This is the VLAN tag VID value. */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_VID_MASK UINT32_C(0xfff)
+ #define PUSH32_DOORBELL_CFA_META_VLAN_VID_SFT 0
+ /* When key=1, This is the VLAN tag DE value. */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_DE UINT32_C(0x1000)
+ /* When key=1, This is the VLAN tag PRI value. */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_PRI_MASK UINT32_C(0xe000)
+ #define PUSH32_DOORBELL_CFA_META_VLAN_PRI_SFT 13
+ /* When key=1, This is the VLAN tag TPID select value. */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_MASK UINT32_C(0x70000)
+ #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_SFT 16
+ /* 0x88a8 */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPID88A8 (UINT32_C(0x0) << 16)
+ /* 0x8100 */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPID8100 (UINT32_C(0x1) << 16)
+ /* 0x9100 */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPID9100 (UINT32_C(0x2) << 16)
+ /* 0x9200 */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPID9200 (UINT32_C(0x3) << 16)
+ /* 0x9300 */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPID9300 (UINT32_C(0x4) << 16)
+ /* Value programmed in CFA VLANTPID register. */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPIDCFG (UINT32_C(0x5) << 16)
+ #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_LAST PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPIDCFG
+ /* When key=1, This is the VLAN tag TPID select value. */
+ #define PUSH32_DOORBELL_CFA_META_VLAN_RESERVED_MASK UINT32_C(0xff80000)
+ #define PUSH32_DOORBELL_CFA_META_VLAN_RESERVED_SFT 19
+ /*
+ * This field identifies the type of edit to be performed on the packet.
+ * This value must be valid on the first BD of a packet.
+ */
+ #define PUSH32_DOORBELL_CFA_META_KEY_MASK UINT32_C(0xf0000000)
+ #define PUSH32_DOORBELL_CFA_META_KEY_SFT 28
+ /* No editing */
+ #define PUSH32_DOORBELL_CFA_META_KEY_NONE (UINT32_C(0x0) << 28)
+ /*
+ * - meta[17:16] - TPID select value (0 = 0x8100). - meta[15:12]
+ * - PRI/DE value. - meta[11:0] - VID value.
+ */
+ #define PUSH32_DOORBELL_CFA_META_KEY_VLAN_TAG (UINT32_C(0x1) << 28)
+ #define PUSH32_DOORBELL_CFA_META_KEY_LAST PUSH32_DOORBELL_CFA_META_KEY_VLAN_TAG
+ uint32_t data[25];
+ /*
+ * This is the data for the push packet. If the packet data does not fit
+ * in the first pass, data writing can continue at offset 4 of the
+ * doorbell for up to 4 additional passes for a total data size of 512B
+ * maximum.
+ */
+} __attribute__((packed));
+
+/* HW Resource Manager Specification 1.4.0 */
+#define HWRM_VERSION_MAJOR 1
+#define HWRM_VERSION_MINOR 4
+#define HWRM_VERSION_UPDATE 0
+
+#define HWRM_VERSION_STR "1.4.0"
+/*
+ * Following is the signature for HWRM message field that indicates not
+ * applicable (All F's). Need to cast it the size of the field if needed.
+ */
+#define HWRM_NA_SIGNATURE ((uint32_t)(-1))
+#define HWRM_MAX_REQ_LEN (128) /* hwrm_func_buf_rgtr */
+#define HWRM_MAX_RESP_LEN (176) /* hwrm_func_qstats */
+#define HW_HASH_INDEX_SIZE 0x80 /* 7 bit indirection table index. */
+#define HW_HASH_KEY_SIZE 40
+#define HWRM_RESP_VALID_KEY 1 /* valid key for HWRM response */
+/*
+ * Description: Port Rx Statistics Formats. The HWRM shall return any
+ * unsupported counter with a value of 0xFFFFFFFF for 32-bit counters and
+ * 0xFFFFFFFFFFFFFFFF for 64-bit counters.
+ */
+/*
+ * Note: The Hardware Resource Manager (HWRM) manages various hardware resources
+ * inside the chip. The HWRM is implemented in firmware, and runs on embedded
+ * processors inside the chip. This firmware service is vital part of the chip.
+ * The chip can not be used by a driver or HWRM client without the HWRM.
+ */
+/* Input (16 bytes) */
+
+struct input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+} __attribute__((packed));
+
+/* Output (8 bytes) */
+
+struct output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+} __attribute__((packed));
+
+#define GET_HWRM_REQ_TYPE(x) \
+ ((x) == 0x98 ? "HWRM_CFA_ENCAP_RECORD_FREE": \
+ ((x) == 0x99 ? "HWRM_CFA_NTUPLE_FILTER_ALLOC": \
+ ((x) == 0x90 ? "HWRM_CFA_L2_FILTER_ALLOC": \
+ ((x) == 0x91 ? "HWRM_CFA_L2_FILTER_FREE": \
+ ((x) == 0x92 ? "HWRM_CFA_L2_FILTER_CFG": \
+ ((x) == 0x93 ? "HWRM_CFA_L2_SET_RX_MASK": \
+ ((x) == 0x94 ? "RESERVED3": \
+ ((x) == 0x95 ? "HWRM_CFA_TUNNEL_FILTER_ALLOC": \
+ ((x) == 0x96 ? "HWRM_CFA_TUNNEL_FILTER_FREE": \
+ ((x) == 0x97 ? "HWRM_CFA_ENCAP_RECORD_ALLOC": \
+ ((x) == 0x10 ? "RESERVED1": \
+ ((x) == 0x11 ? "HWRM_FUNC_RESET": \
+ ((x) == 0x12 ? "HWRM_FUNC_GETFID": \
+ ((x) == 0x13 ? "HWRM_FUNC_VF_ALLOC": \
+ ((x) == 0x14 ? "HWRM_FUNC_VF_FREE": \
+ ((x) == 0x15 ? "HWRM_FUNC_QCAPS": \
+ ((x) == 0x16 ? "HWRM_FUNC_QCFG": \
+ ((x) == 0x17 ? "HWRM_FUNC_CFG": \
+ ((x) == 0x18 ? "HWRM_FUNC_QSTATS": \
+ ((x) == 0x19 ? "HWRM_FUNC_CLR_STATS": \
+ ((x) == 0xe0 ? "HWRM_TEMP_MONITOR_QUERY": \
+ ((x) == 0xd3 ? "HWRM_FWD_ASYNC_EVENT_CMPL": \
+ ((x) == 0xd2 ? "HWRM_FWD_RESP": \
+ ((x) == 0x1a ? "HWRM_FUNC_DRV_UNRGTR": \
+ ((x) == 0x1b ? "HWRM_FUNC_VF_RESC_FREE": \
+ ((x) == 0x1c ? "HWRM_FUNC_VF_VNIC_IDS_QUERY": \
+ ((x) == 0x1d ? "HWRM_FUNC_DRV_RGTR": \
+ ((x) == 0x1e ? "HWRM_FUNC_DRV_QVER": \
+ ((x) == 0x1f ? "HWRM_FUNC_BUF_RGTR": \
+ ((x) == 0x9a ? "HWRM_CFA_NTUPLE_FILTER_FREE": \
+ ((x) == 0x9b ? "HWRM_CFA_NTUPLE_FILTER_CFG": \
+ ((x) == 0x9c ? "HWRM_CFA_EM_FLOW_ALLOC": \
+ ((x) == 0x9d ? "HWRM_CFA_EM_FLOW_FREE": \
+ ((x) == 0x9e ? "HWRM_CFA_EM_FLOW_CFG": \
+ ((x) == 0xd1 ? "HWRM_REJECT_FWD_RESP": \
+ ((x) == 0xd0 ? "HWRM_EXEC_FWD_RESP": \
+ ((x) == 0xc8 ? "HWRM_FW_SET_TIME": \
+ ((x) == 0xc9 ? "HWRM_FW_GET_TIME": \
+ ((x) == 0xc0 ? "HWRM_FW_RESET": \
+ ((x) == 0xc1 ? "HWRM_FW_QSTATUS": \
+ ((x) == 0x70 ? "HWRM_VNIC_RSS_COS_LB_CTX_ALLOC": \
+ ((x) == 0x71 ? "HWRM_VNIC_RSS_COS_LB_CTX_FREE": \
+ ((x) == 0xb1 ? "HWRM_STAT_CTX_FREE": \
+ ((x) == 0xb0 ? "HWRM_STAT_CTX_ALLOC": \
+ ((x) == 0xb3 ? "HWRM_STAT_CTX_CLR_STATS": \
+ ((x) == 0xb2 ? "HWRM_STAT_CTX_QUERY": \
+ ((x) == 0xfff6 ? "HWRM_NVM_GET_DEV_INFO": \
+ ((x) == 0x61 ? "HWRM_RING_GRP_FREE": \
+ ((x) == 0x60 ? "HWRM_RING_GRP_ALLOC": \
+ ((x) == 0xf1 ? "HWRM_WOL_FILTER_FREE": \
+ ((x) == 0xf0 ? "HWRM_WOL_FILTER_ALLOC": \
+ ((x) == 0xf3 ? "HWRM_WOL_REASON_QCFG": \
+ ((x) == 0xf2 ? "HWRM_WOL_FILTER_QCFG": \
+ ((x) == 0xa0 ? "HWRM_TUNNEL_DST_PORT_QUERY": \
+ ((x) == 0xa1 ? "HWRM_TUNNEL_DST_PORT_ALLOC": \
+ ((x) == 0xa2 ? "HWRM_TUNNEL_DST_PORT_FREE": \
+ ((x) == 0xfffc ? "HWRM_NVM_RAW_DUMP": \
+ ((x) == 0xfffb ? "HWRM_NVM_GET_DIR_INFO": \
+ ((x) == 0xfffa ? "HWRM_NVM_GET_DIR_ENTRIES": \
+ ((x) == 0xe ? "HWRM_FUNC_BUF_UNRGTR": \
+ ((x) == 0xf ? "HWRM_FUNC_VF_CFG": \
+ ((x) == 0xffff ? "HWRM_NVM_RAW_WRITE_BLK": \
+ ((x) == 0xfffe ? "HWRM_NVM_WRITE": \
+ ((x) == 0xfffd ? "HWRM_NVM_READ": \
+ ((x) == 0x50 ? "HWRM_RING_ALLOC": \
+ ((x) == 0x51 ? "HWRM_RING_FREE": \
+ ((x) == 0x52 ? "HWRM_RING_CMPL_RING_QAGGINT_PARAMS": \
+ ((x) == 0x53 ? "HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS": \
+ ((x) == 0x4a ? "HWRM_VNIC_QCAPS": \
+ ((x) == 0x49 ? "HWRM_VNIC_PLCMODES_QCFG": \
+ ((x) == 0x48 ? "HWRM_VNIC_PLCMODES_CFG": \
+ ((x) == 0x47 ? "HWRM_VNIC_RSS_QCFG": \
+ ((x) == 0x46 ? "HWRM_VNIC_RSS_CFG": \
+ ((x) == 0x45 ? "HWRM_VNIC_TPA_QCFG": \
+ ((x) == 0x44 ? "HWRM_VNIC_TPA_CFG": \
+ ((x) == 0x43 ? "HWRM_VNIC_QCFG": \
+ ((x) == 0x42 ? "HWRM_VNIC_CFG": \
+ ((x) == 0x41 ? "HWRM_VNIC_FREE": \
+ ((x) == 0x40 ? "HWRM_VNIC_ALLOC": \
+ ((x) == 0x0 ? "HWRM_VER_GET": \
+ ((x) == 0xfff9 ? "HWRM_NVM_FIND_DIR_ENTRY": \
+ ((x) == 0xfff8 ? "HWRM_NVM_MOD_DIR_ENTRY": \
+ ((x) == 0xfff7 ? "HWRM_NVM_ERASE_DIR_ENTRY": \
+ ((x) == 0x5e ? "HWRM_RING_RESET": \
+ ((x) == 0xfff5 ? "HWRM_NVM_VERIFY_UPDATE": \
+ ((x) == 0xfff4 ? "HWRM_NVM_MODIFY": \
+ ((x) == 0xfff3 ? "HWRM_NVM_INSTALL_UPDATE": \
+ ((x) == 0x2a ? "HWRM_PORT_PHY_QCAPS": \
+ ((x) == 0x2c ? "HWRM_PORT_PHY_I2C_READ": \
+ ((x) == 0x2b ? "HWRM_PORT_PHY_I2C_WRITE": \
+ ((x) == 0x38 ? "HWRM_QUEUE_PRI2COS_CFG": \
+ ((x) == 0x39 ? "HWRM_QUEUE_COS2BW_QCFG": \
+ ((x) == 0x32 ? "HWRM_QUEUE_CFG": \
+ ((x) == 0x33 ? "HWRM_QUEUE_BUFFERS_QCFG": \
+ ((x) == 0x30 ? "HWRM_QUEUE_QPORTCFG": \
+ ((x) == 0x31 ? "HWRM_QUEUE_QCFG": \
+ ((x) == 0x36 ? "HWRM_QUEUE_PFCENABLE_CFG": \
+ ((x) == 0x37 ? "HWRM_QUEUE_PRI2COS_QCFG": \
+ ((x) == 0x34 ? "HWRM_QUEUE_BUFFERS_CFG": \
+ ((x) == 0x35 ? "HWRM_QUEUE_PFCENABLE_QCFG": \
+ ((x) == 0xff14 ? "HWRM_DBG_DUMP": \
+ ((x) == 0xff12 ? "HWRM_DBG_WRITE_DIRECT": \
+ ((x) == 0xff13 ? "HWRM_DBG_WRITE_INDIRECT": \
+ ((x) == 0xff10 ? "HWRM_DBG_READ_DIRECT": \
+ ((x) == 0xff11 ? "HWRM_DBG_READ_INDIRECT": \
+ ((x) == 0x25 ? "HWRM_PORT_CLR_STATS": \
+ ((x) == 0x24 ? "HWRM_PORT_LPBK_QSTATS": \
+ ((x) == 0x27 ? "HWRM_PORT_PHY_QCFG": \
+ ((x) == 0x26 ? "HWRM_PORT_LPBK_CLR_STATS": \
+ ((x) == 0x21 ? "HWRM_PORT_MAC_CFG": \
+ ((x) == 0x20 ? "HWRM_PORT_PHY_CFG": \
+ ((x) == 0x23 ? "HWRM_PORT_QSTATS": \
+ ((x) == 0x22 ? "HWRM_PORT_TS_QUERY": \
+ ((x) == 0x29 ? "HWRM_PORT_BLINK_LED": \
+ ((x) == 0x28 ? "HWRM_PORT_MAC_QCFG": \
+ ((x) == 0x3a ? "HWRM_QUEUE_COS2BW_CFG": \
+ "Unknown req_type"))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+
+/* Command numbering (8 bytes) */
+
+struct cmd_nums {
+ uint16_t req_type;
+ /*
+ * This version of the specification defines the commands listed in the
+ * table below. The following are general implementation requirements
+ * for these commands: # All commands listed below that are marked
+ * neither reserved nor experimental shall be implemented by the HWRM. #
+ * A HWRM client compliant to this specification should not use commands
+ * outside of the list below. # A HWRM client compliant to this
+ * specification should not use command numbers marked reserved below. #
+ * A command marked experimental below may not be implemented by the
+ * HWRM. # A command marked experimental may change in the future
+ * version of the HWRM specification. # A command not listed below may
+ * be implemented by the HWRM. The behavior of commands that are not
+ * listed below is outside the scope of this specification.
+ */
+ #define HWRM_VER_GET (UINT32_C(0x0))
+ #define HWRM_FUNC_BUF_UNRGTR (UINT32_C(0xe))
+ /* Experimental */
+ #define HWRM_FUNC_VF_CFG (UINT32_C(0xf))
+ /* Reserved for future use */
+ #define RESERVED1 (UINT32_C(0x10))
+ #define HWRM_FUNC_RESET (UINT32_C(0x11))
+ #define HWRM_FUNC_GETFID (UINT32_C(0x12))
+ #define HWRM_FUNC_VF_ALLOC (UINT32_C(0x13))
+ #define HWRM_FUNC_VF_FREE (UINT32_C(0x14))
+ #define HWRM_FUNC_QCAPS (UINT32_C(0x15))
+ #define HWRM_FUNC_QCFG (UINT32_C(0x16))
+ #define HWRM_FUNC_CFG (UINT32_C(0x17))
+ #define HWRM_FUNC_QSTATS (UINT32_C(0x18))
+ #define HWRM_FUNC_CLR_STATS (UINT32_C(0x19))
+ #define HWRM_FUNC_DRV_UNRGTR (UINT32_C(0x1a))
+ #define HWRM_FUNC_VF_RESC_FREE (UINT32_C(0x1b))
+ #define HWRM_FUNC_VF_VNIC_IDS_QUERY (UINT32_C(0x1c))
+ #define HWRM_FUNC_DRV_RGTR (UINT32_C(0x1d))
+ #define HWRM_FUNC_DRV_QVER (UINT32_C(0x1e))
+ #define HWRM_FUNC_BUF_RGTR (UINT32_C(0x1f))
+ #define HWRM_PORT_PHY_CFG (UINT32_C(0x20))
+ #define HWRM_PORT_MAC_CFG (UINT32_C(0x21))
+ /* Experimental */
+ #define HWRM_PORT_TS_QUERY (UINT32_C(0x22))
+ #define HWRM_PORT_QSTATS (UINT32_C(0x23))
+ #define HWRM_PORT_LPBK_QSTATS (UINT32_C(0x24))
+ /* Experimental */
+ #define HWRM_PORT_CLR_STATS (UINT32_C(0x25))
+ /* Experimental */
+ #define HWRM_PORT_LPBK_CLR_STATS (UINT32_C(0x26))
+ #define HWRM_PORT_PHY_QCFG (UINT32_C(0x27))
+ /* Experimental */
+ #define HWRM_PORT_MAC_QCFG (UINT32_C(0x28))
+ /* Experimental */
+ #define HWRM_PORT_BLINK_LED (UINT32_C(0x29))
+ /* Experimental */
+ #define HWRM_PORT_PHY_QCAPS (UINT32_C(0x2a))
+ /* Experimental */
+ #define HWRM_PORT_PHY_I2C_WRITE (UINT32_C(0x2b))
+ /* Experimental */
+ #define HWRM_PORT_PHY_I2C_READ (UINT32_C(0x2c))
+ #define HWRM_QUEUE_QPORTCFG (UINT32_C(0x30))
+ #define HWRM_QUEUE_QCFG (UINT32_C(0x31))
+ #define HWRM_QUEUE_CFG (UINT32_C(0x32))
+ #define HWRM_QUEUE_BUFFERS_QCFG (UINT32_C(0x33))
+ #define HWRM_QUEUE_BUFFERS_CFG (UINT32_C(0x34))
+ /* Experimental */
+ #define HWRM_QUEUE_PFCENABLE_QCFG (UINT32_C(0x35))
+ /* Experimental */
+ #define HWRM_QUEUE_PFCENABLE_CFG (UINT32_C(0x36))
+ /* Experimental */
+ #define HWRM_QUEUE_PRI2COS_QCFG (UINT32_C(0x37))
+ /* Experimental */
+ #define HWRM_QUEUE_PRI2COS_CFG (UINT32_C(0x38))
+ /* Experimental */
+ #define HWRM_QUEUE_COS2BW_QCFG (UINT32_C(0x39))
+ /* Experimental */
+ #define HWRM_QUEUE_COS2BW_CFG (UINT32_C(0x3a))
+ #define HWRM_VNIC_ALLOC (UINT32_C(0x40))
+ #define HWRM_VNIC_FREE (UINT32_C(0x41))
+ #define HWRM_VNIC_CFG (UINT32_C(0x42))
+ /* Experimental */
+ #define HWRM_VNIC_QCFG (UINT32_C(0x43))
+ #define HWRM_VNIC_TPA_CFG (UINT32_C(0x44))
+ /* Experimental */
+ #define HWRM_VNIC_TPA_QCFG (UINT32_C(0x45))
+ #define HWRM_VNIC_RSS_CFG (UINT32_C(0x46))
+ #define HWRM_VNIC_RSS_QCFG (UINT32_C(0x47))
+ #define HWRM_VNIC_PLCMODES_CFG (UINT32_C(0x48))
+ #define HWRM_VNIC_PLCMODES_QCFG (UINT32_C(0x49))
+ /* Experimental */
+ #define HWRM_VNIC_QCAPS (UINT32_C(0x4a))
+ #define HWRM_RING_ALLOC (UINT32_C(0x50))
+ #define HWRM_RING_FREE (UINT32_C(0x51))
+ #define HWRM_RING_CMPL_RING_QAGGINT_PARAMS (UINT32_C(0x52))
+ #define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS (UINT32_C(0x53))
+ #define HWRM_RING_RESET (UINT32_C(0x5e))
+ #define HWRM_RING_GRP_ALLOC (UINT32_C(0x60))
+ #define HWRM_RING_GRP_FREE (UINT32_C(0x61))
+ #define HWRM_VNIC_RSS_COS_LB_CTX_ALLOC (UINT32_C(0x70))
+ #define HWRM_VNIC_RSS_COS_LB_CTX_FREE (UINT32_C(0x71))
+ #define HWRM_CFA_L2_FILTER_ALLOC (UINT32_C(0x90))
+ #define HWRM_CFA_L2_FILTER_FREE (UINT32_C(0x91))
+ #define HWRM_CFA_L2_FILTER_CFG (UINT32_C(0x92))
+ #define HWRM_CFA_L2_SET_RX_MASK (UINT32_C(0x93))
+ /* Reserved for future use */
+ #define RESERVED3 (UINT32_C(0x94))
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC (UINT32_C(0x95))
+ #define HWRM_CFA_TUNNEL_FILTER_FREE (UINT32_C(0x96))
+ /* Experimental */
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC (UINT32_C(0x97))
+ /* Experimental */
+ #define HWRM_CFA_ENCAP_RECORD_FREE (UINT32_C(0x98))
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC (UINT32_C(0x99))
+ #define HWRM_CFA_NTUPLE_FILTER_FREE (UINT32_C(0x9a))
+ #define HWRM_CFA_NTUPLE_FILTER_CFG (UINT32_C(0x9b))
+ /* Experimental */
+ #define HWRM_CFA_EM_FLOW_ALLOC (UINT32_C(0x9c))
+ /* Experimental */
+ #define HWRM_CFA_EM_FLOW_FREE (UINT32_C(0x9d))
+ /* Experimental */
+ #define HWRM_CFA_EM_FLOW_CFG (UINT32_C(0x9e))
+ #define HWRM_TUNNEL_DST_PORT_QUERY (UINT32_C(0xa0))
+ #define HWRM_TUNNEL_DST_PORT_ALLOC (UINT32_C(0xa1))
+ #define HWRM_TUNNEL_DST_PORT_FREE (UINT32_C(0xa2))
+ #define HWRM_STAT_CTX_ALLOC (UINT32_C(0xb0))
+ #define HWRM_STAT_CTX_FREE (UINT32_C(0xb1))
+ #define HWRM_STAT_CTX_QUERY (UINT32_C(0xb2))
+ #define HWRM_STAT_CTX_CLR_STATS (UINT32_C(0xb3))
+ #define HWRM_FW_RESET (UINT32_C(0xc0))
+ #define HWRM_FW_QSTATUS (UINT32_C(0xc1))
+ /* Experimental */
+ #define HWRM_FW_SET_TIME (UINT32_C(0xc8))
+ /* Experimental */
+ #define HWRM_FW_GET_TIME (UINT32_C(0xc9))
+ #define HWRM_EXEC_FWD_RESP (UINT32_C(0xd0))
+ #define HWRM_REJECT_FWD_RESP (UINT32_C(0xd1))
+ #define HWRM_FWD_RESP (UINT32_C(0xd2))
+ #define HWRM_FWD_ASYNC_EVENT_CMPL (UINT32_C(0xd3))
+ #define HWRM_TEMP_MONITOR_QUERY (UINT32_C(0xe0))
+ /* Experimental */
+ #define HWRM_WOL_FILTER_ALLOC (UINT32_C(0xf0))
+ /* Experimental */
+ #define HWRM_WOL_FILTER_FREE (UINT32_C(0xf1))
+ /* Experimental */
+ #define HWRM_WOL_FILTER_QCFG (UINT32_C(0xf2))
+ /* Experimental */
+ #define HWRM_WOL_REASON_QCFG (UINT32_C(0xf3))
+ /* Experimental */
+ #define HWRM_DBG_READ_DIRECT (UINT32_C(0xff10))
+ /* Experimental */
+ #define HWRM_DBG_READ_INDIRECT (UINT32_C(0xff11))
+ /* Experimental */
+ #define HWRM_DBG_WRITE_DIRECT (UINT32_C(0xff12))
+ /* Experimental */
+ #define HWRM_DBG_WRITE_INDIRECT (UINT32_C(0xff13))
+ #define HWRM_DBG_DUMP (UINT32_C(0xff14))
+ #define HWRM_NVM_INSTALL_UPDATE (UINT32_C(0xfff3))
+ #define HWRM_NVM_MODIFY (UINT32_C(0xfff4))
+ #define HWRM_NVM_VERIFY_UPDATE (UINT32_C(0xfff5))
+ #define HWRM_NVM_GET_DEV_INFO (UINT32_C(0xfff6))
+ #define HWRM_NVM_ERASE_DIR_ENTRY (UINT32_C(0xfff7))
+ #define HWRM_NVM_MOD_DIR_ENTRY (UINT32_C(0xfff8))
+ #define HWRM_NVM_FIND_DIR_ENTRY (UINT32_C(0xfff9))
+ #define HWRM_NVM_GET_DIR_ENTRIES (UINT32_C(0xfffa))
+ #define HWRM_NVM_GET_DIR_INFO (UINT32_C(0xfffb))
+ #define HWRM_NVM_RAW_DUMP (UINT32_C(0xfffc))
+ #define HWRM_NVM_READ (UINT32_C(0xfffd))
+ #define HWRM_NVM_WRITE (UINT32_C(0xfffe))
+ #define HWRM_NVM_RAW_WRITE_BLK (UINT32_C(0xffff))
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+#define GET_HWRM_ERROR_CODE(x) \
+ ((x) == 0xf ? "HWRM_ERROR": \
+ ((x) == 0xffff ? "CMD_NOT_SUPPORTED": \
+ ((x) == 0xfffe ? "UNKNOWN_ERR": \
+ ((x) == 0x4 ? "RESOURCE_ALLOC_ERROR": \
+ ((x) == 0x5 ? "INVALID_FLAGS": \
+ ((x) == 0x6 ? "INVALID_ENABLES": \
+ ((x) == 0x0 ? "SUCCESS": \
+ ((x) == 0x1 ? "FAIL": \
+ ((x) == 0x2 ? "INVALID_PARAMS": \
+ ((x) == 0x3 ? "RESOURCE_ACCESS_DENIED": \
+ "Unknown error_code"))))))))))
+
+/* Return Codes (8 bytes) */
+
+struct ret_codes {
+ uint16_t error_code;
+ /* These are numbers assigned to return/error codes. */
+ /* Request was successfully executed by the HWRM. */
+ #define HWRM_ERR_CODE_SUCCESS (UINT32_C(0x0))
+ /* THe HWRM failed to execute the request. */
+ #define HWRM_ERR_CODE_FAIL (UINT32_C(0x1))
+ /* The request contains invalid argument(s) or input parameters. */
+ #define HWRM_ERR_CODE_INVALID_PARAMS (UINT32_C(0x2))
+ /*
+ * The requester is not allowed to access the requested
+ * resource. This error code shall be provided in a response to
+ * a request to query or modify an existing resource that is not
+ * accessible by the requester.
+ */
+ #define HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED (UINT32_C(0x3))
+ /*
+ * The HWRM is unable to allocate the requested resource. This
+ * code only applies to requests for HWRM resource allocations.
+ */
+ #define HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR (UINT32_C(0x4))
+ /* Invalid combination of flags is specified in the request. */
+ #define HWRM_ERR_CODE_INVALID_FLAGS (UINT32_C(0x5))
+ /*
+ * Invalid combination of enables fields is specified in the
+ * request.
+ */
+ #define HWRM_ERR_CODE_INVALID_ENABLES (UINT32_C(0x6))
+ /* Generic HWRM execution error that represents an internal error. */
+ #define HWRM_ERR_CODE_HWRM_ERROR (UINT32_C(0xf))
+ /* Unknown error */
+ #define HWRM_ERR_CODE_UNKNOWN_ERR (UINT32_C(0xfffe))
+ /* Unsupported or invalid command */
+ #define HWRM_ERR_CODE_CMD_NOT_SUPPORTED (UINT32_C(0xffff))
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_err_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t opaque_0;
+ /* debug info for this error response. */
+ uint16_t opaque_1;
+ /* debug info for this error response. */
+ uint8_t cmd_err;
+ /*
+ * In the case of an error response, command specific error code is
+ * returned in this field.
+ */
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* Port Tx Statistics Formats (408 bytes) */
+
+struct tx_port_stats {
+ uint64_t tx_64b_frames;
+ /* Total Number of 64 Bytes frames transmitted */
+ uint64_t tx_65b_127b_frames;
+ /* Total Number of 65-127 Bytes frames transmitted */
+ uint64_t tx_128b_255b_frames;
+ /* Total Number of 128-255 Bytes frames transmitted */
+ uint64_t tx_256b_511b_frames;
+ /* Total Number of 256-511 Bytes frames transmitted */
+ uint64_t tx_512b_1023b_frames;
+ /* Total Number of 512-1023 Bytes frames transmitted */
+ uint64_t tx_1024b_1518_frames;
+ /* Total Number of 1024-1518 Bytes frames transmitted */
+ uint64_t tx_good_vlan_frames;
+ /*
+ * Total Number of each good VLAN (exludes FCS errors) frame transmitted
+ * which is 1519 to 1522 bytes in length inclusive (excluding framing
+ * bits but including FCS bytes).
+ */
+ uint64_t tx_1519b_2047_frames;
+ /* Total Number of 1519-2047 Bytes frames transmitted */
+ uint64_t tx_2048b_4095b_frames;
+ /* Total Number of 2048-4095 Bytes frames transmitted */
+ uint64_t tx_4096b_9216b_frames;
+ /* Total Number of 4096-9216 Bytes frames transmitted */
+ uint64_t tx_9217b_16383b_frames;
+ /* Total Number of 9217-16383 Bytes frames transmitted */
+ uint64_t tx_good_frames;
+ /* Total Number of good frames transmitted */
+ uint64_t tx_total_frames;
+ /* Total Number of frames transmitted */
+ uint64_t tx_ucast_frames;
+ /* Total number of unicast frames transmitted */
+ uint64_t tx_mcast_frames;
+ /* Total number of multicast frames transmitted */
+ uint64_t tx_bcast_frames;
+ /* Total number of broadcast frames transmitted */
+ uint64_t tx_pause_frames;
+ /* Total number of PAUSE control frames transmitted */
+ uint64_t tx_pfc_frames;
+ /* Total number of PFC/per-priority PAUSE control frames transmitted */
+ uint64_t tx_jabber_frames;
+ /* Total number of jabber frames transmitted */
+ uint64_t tx_fcs_err_frames;
+ /* Total number of frames transmitted with FCS error */
+ uint64_t tx_control_frames;
+ /* Total number of control frames transmitted */
+ uint64_t tx_oversz_frames;
+ /* Total number of over-sized frames transmitted */
+ uint64_t tx_single_dfrl_frames;
+ /* Total number of frames with single deferral */
+ uint64_t tx_multi_dfrl_frames;
+ /* Total number of frames with multiple deferrals */
+ uint64_t tx_single_coll_frames;
+ /* Total number of frames with single collision */
+ uint64_t tx_multi_coll_frames;
+ /* Total number of frames with multiple collisions */
+ uint64_t tx_late_coll_frames;
+ /* Total number of frames with late collisions */
+ uint64_t tx_excessive_coll_frames;
+ /* Total number of frames with excessive collisions */
+ uint64_t tx_frag_frames;
+ /* Total number of fragmented frames transmitted */
+ uint64_t tx_err;
+ /* Total number of transmit errors */
+ uint64_t tx_tagged_frames;
+ /* Total number of single VLAN tagged frames transmitted */
+ uint64_t tx_dbl_tagged_frames;
+ /* Total number of double VLAN tagged frames transmitted */
+ uint64_t tx_runt_frames;
+ /* Total number of runt frames transmitted */
+ uint64_t tx_fifo_underruns;
+ /* Total number of TX FIFO under runs */
+ uint64_t tx_pfc_ena_frames_pri0;
+ /* Total number of PFC frames with PFC enabled bit for Pri 0 transmitted */
+ uint64_t tx_pfc_ena_frames_pri1;
+ /* Total number of PFC frames with PFC enabled bit for Pri 1 transmitted */
+ uint64_t tx_pfc_ena_frames_pri2;
+ /* Total number of PFC frames with PFC enabled bit for Pri 2 transmitted */
+ uint64_t tx_pfc_ena_frames_pri3;
+ /* Total number of PFC frames with PFC enabled bit for Pri 3 transmitted */
+ uint64_t tx_pfc_ena_frames_pri4;
+ /* Total number of PFC frames with PFC enabled bit for Pri 4 transmitted */
+ uint64_t tx_pfc_ena_frames_pri5;
+ /* Total number of PFC frames with PFC enabled bit for Pri 5 transmitted */
+ uint64_t tx_pfc_ena_frames_pri6;
+ /* Total number of PFC frames with PFC enabled bit for Pri 6 transmitted */
+ uint64_t tx_pfc_ena_frames_pri7;
+ /* Total number of PFC frames with PFC enabled bit for Pri 7 transmitted */
+ uint64_t tx_eee_lpi_events;
+ /* Total number of EEE LPI Events on TX */
+ uint64_t tx_eee_lpi_duration;
+ /* EEE LPI Duration Counter on TX */
+ uint64_t tx_llfc_logical_msgs;
+ /* Total number of Link Level Flow Control (LLFC) messages transmitted */
+ uint64_t tx_hcfc_msgs;
+ /* Total number of HCFC messages transmitted */
+ uint64_t tx_total_collisions;
+ /* Total number of TX collisions */
+ uint64_t tx_bytes;
+ /* Total number of transmitted bytes */
+ uint64_t tx_xthol_frames;
+ /* Total number of end-to-end HOL frames */
+ uint64_t tx_stat_discard;
+ /* Total Tx Drops per Port reported by STATS block */
+ uint64_t tx_stat_error;
+ /* Total Tx Error Drops per Port reported by STATS block */
+} __attribute__((packed));
+
+/* Port Rx Statistics Formats (528 bytes) */
+
+struct rx_port_stats {
+ uint64_t rx_64b_frames;
+ /* Total Number of 64 Bytes frames received */
+ uint64_t rx_65b_127b_frames;
+ /* Total Number of 65-127 Bytes frames received */
+ uint64_t rx_128b_255b_frames;
+ /* Total Number of 128-255 Bytes frames received */
+ uint64_t rx_256b_511b_frames;
+ /* Total Number of 256-511 Bytes frames received */
+ uint64_t rx_512b_1023b_frames;
+ /* Total Number of 512-1023 Bytes frames received */
+ uint64_t rx_1024b_1518_frames;
+ /* Total Number of 1024-1518 Bytes frames received */
+ uint64_t rx_good_vlan_frames;
+ /*
+ * Total Number of each good VLAN (exludes FCS errors) frame received
+ * which is 1519 to 1522 bytes in length inclusive (excluding framing
+ * bits but including FCS bytes).
+ */
+ uint64_t rx_1519b_2047b_frames;
+ /* Total Number of 1519-2047 Bytes frames received */
+ uint64_t rx_2048b_4095b_frames;
+ /* Total Number of 2048-4095 Bytes frames received */
+ uint64_t rx_4096b_9216b_frames;
+ /* Total Number of 4096-9216 Bytes frames received */
+ uint64_t rx_9217b_16383b_frames;
+ /* Total Number of 9217-16383 Bytes frames received */
+ uint64_t rx_total_frames;
+ /* Total number of frames received */
+ uint64_t rx_ucast_frames;
+ /* Total number of unicast frames received */
+ uint64_t rx_mcast_frames;
+ /* Total number of multicast frames received */
+ uint64_t rx_bcast_frames;
+ /* Total number of broadcast frames received */
+ uint64_t rx_fcs_err_frames;
+ /* Total number of received frames with FCS error */
+ uint64_t rx_ctrl_frames;
+ /* Total number of control frames received */
+ uint64_t rx_pause_frames;
+ /* Total number of PAUSE frames received */
+ uint64_t rx_pfc_frames;
+ /* Total number of PFC frames received */
+ uint64_t rx_unsupported_opcode_frames;
+ /* Total number of frames received with an unsupported opcode */
+ uint64_t rx_unsupported_da_pausepfc_frames;
+ /*
+ * Total number of frames received with an unsupported DA for pause and
+ * PFC
+ */
+ uint64_t rx_wrong_sa_frames;
+ /* Total number of frames received with an unsupported SA */
+ uint64_t rx_align_err_frames;
+ /* Total number of received packets with alignment error */
+ uint64_t rx_oor_len_frames;
+ /* Total number of received frames with out-of-range length */
+ uint64_t rx_code_err_frames;
+ /* Total number of received frames with error termination */
+ uint64_t rx_false_carrier_frames;
+ /*
+ * Total number of received frames with a false carrier is detected
+ * during idle, as defined by RX_ER samples active and RXD is 0xE. The
+ * event is reported along with the statistics generated on the next
+ * received frame. Only one false carrier condition can be detected and
+ * logged between frames. Carrier event, valid for 10M/100M speed modes
+ * only.
+ */
+ uint64_t rx_ovrsz_frames;
+ /* Total number of over-sized frames received */
+ uint64_t rx_jbr_frames;
+ /* Total number of jabber packets received */
+ uint64_t rx_mtu_err_frames;
+ /* Total number of received frames with MTU error */
+ uint64_t rx_match_crc_frames;
+ /* Total number of received frames with CRC match */
+ uint64_t rx_promiscuous_frames;
+ /* Total number of frames received promiscuously */
+ uint64_t rx_tagged_frames;
+ /* Total number of received frames with one or two VLAN tags */
+ uint64_t rx_double_tagged_frames;
+ /* Total number of received frames with two VLAN tags */
+ uint64_t rx_trunc_frames;
+ /* Total number of truncated frames received */
+ uint64_t rx_good_frames;
+ /* Total number of good frames (without errors) received */
+ uint64_t rx_pfc_xon2xoff_frames_pri0;
+ /*
+ * Total number of received PFC frames with transition from XON to XOFF
+ * on Pri 0
+ */
+ uint64_t rx_pfc_xon2xoff_frames_pri1;
+ /*
+ * Total number of received PFC frames with transition from XON to XOFF
+ * on Pri 1
+ */
+ uint64_t rx_pfc_xon2xoff_frames_pri2;
+ /*
+ * Total number of received PFC frames with transition from XON to XOFF
+ * on Pri 2
+ */
+ uint64_t rx_pfc_xon2xoff_frames_pri3;
+ /*
+ * Total number of received PFC frames with transition from XON to XOFF
+ * on Pri 3
+ */
+ uint64_t rx_pfc_xon2xoff_frames_pri4;
+ /*
+ * Total number of received PFC frames with transition from XON to XOFF
+ * on Pri 4
+ */
+ uint64_t rx_pfc_xon2xoff_frames_pri5;
+ /*
+ * Total number of received PFC frames with transition from XON to XOFF
+ * on Pri 5
+ */
+ uint64_t rx_pfc_xon2xoff_frames_pri6;
+ /*
+ * Total number of received PFC frames with transition from XON to XOFF
+ * on Pri 6
+ */
+ uint64_t rx_pfc_xon2xoff_frames_pri7;
+ /*
+ * Total number of received PFC frames with transition from XON to XOFF
+ * on Pri 7
+ */
+ uint64_t rx_pfc_ena_frames_pri0;
+ /* Total number of received PFC frames with PFC enabled bit for Pri 0 */
+ uint64_t rx_pfc_ena_frames_pri1;
+ /* Total number of received PFC frames with PFC enabled bit for Pri 1 */
+ uint64_t rx_pfc_ena_frames_pri2;
+ /* Total number of received PFC frames with PFC enabled bit for Pri 2 */
+ uint64_t rx_pfc_ena_frames_pri3;
+ /* Total number of received PFC frames with PFC enabled bit for Pri 3 */
+ uint64_t rx_pfc_ena_frames_pri4;
+ /* Total number of received PFC frames with PFC enabled bit for Pri 4 */
+ uint64_t rx_pfc_ena_frames_pri5;
+ /* Total number of received PFC frames with PFC enabled bit for Pri 5 */
+ uint64_t rx_pfc_ena_frames_pri6;
+ /* Total number of received PFC frames with PFC enabled bit for Pri 6 */
+ uint64_t rx_pfc_ena_frames_pri7;
+ /* Total number of received PFC frames with PFC enabled bit for Pri 7 */
+ uint64_t rx_sch_crc_err_frames;
+ /* Total Number of frames received with SCH CRC error */
+ uint64_t rx_undrsz_frames;
+ /* Total Number of under-sized frames received */
+ uint64_t rx_frag_frames;
+ /* Total Number of fragmented frames received */
+ uint64_t rx_eee_lpi_events;
+ /* Total number of RX EEE LPI Events */
+ uint64_t rx_eee_lpi_duration;
+ /* EEE LPI Duration Counter on RX */
+ uint64_t rx_llfc_physical_msgs;
+ /*
+ * Total number of physical type Link Level Flow Control (LLFC) messages
+ * received
+ */
+ uint64_t rx_llfc_logical_msgs;
+ /*
+ * Total number of logical type Link Level Flow Control (LLFC) messages
+ * received
+ */
+ uint64_t rx_llfc_msgs_with_crc_err;
+ /*
+ * Total number of logical type Link Level Flow Control (LLFC) messages
+ * received with CRC error
+ */
+ uint64_t rx_hcfc_msgs;
+ /* Total number of HCFC messages received */
+ uint64_t rx_hcfc_msgs_with_crc_err;
+ /* Total number of HCFC messages received with CRC error */
+ uint64_t rx_bytes;
+ /* Total number of received bytes */
+ uint64_t rx_runt_bytes;
+ /* Total number of bytes received in runt frames */
+ uint64_t rx_runt_frames;
+ /* Total number of runt frames received */
+ uint64_t rx_stat_discard;
+ /* Total Rx Discards per Port reported by STATS block */
+ uint64_t rx_stat_err;
+ /* Total Rx Error Drops per Port reported by STATS block */
+} __attribute__((packed));
+
+/* hwrm_ver_get */
+/*
+ * Description: This function is called by a driver to determine the HWRM
+ * interface version supported by the HWRM firmware, the version of HWRM
+ * firmware implementation, the name of HWRM firmware, the versions of other
+ * embedded firmwares, and the names of other embedded firmwares, etc. Any
+ * interface or firmware version with major = 0, minor = 0, and update = 0 shall
+ * be considered an invalid version.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_ver_get_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint8_t hwrm_intf_maj;
+ /*
+ * This field represents the major version of HWRM interface
+ * specification supported by the driver HWRM implementation. The
+ * interface major version is intended to change only when non backward
+ * compatible changes are made to the HWRM interface specification.
+ */
+ uint8_t hwrm_intf_min;
+ /*
+ * This field represents the minor version of HWRM interface
+ * specification supported by the driver HWRM implementation. A change
+ * in interface minor version is used to reflect significant backward
+ * compatible modification to HWRM interface specification. This can be
+ * due to addition or removal of functionality. HWRM interface
+ * specifications with the same major version but different minor
+ * versions are compatible.
+ */
+ uint8_t hwrm_intf_upd;
+ /*
+ * This field represents the update version of HWRM interface
+ * specification supported by the driver HWRM implementation. The
+ * interface update version is used to reflect minor changes or bug
+ * fixes to a released HWRM interface specification.
+ */
+ uint8_t unused_0[5];
+} __attribute__((packed));
+
+/* Output (128 bytes) */
+
+struct hwrm_ver_get_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t hwrm_intf_maj;
+ /*
+ * This field represents the major version of HWRM interface
+ * specification supported by the HWRM implementation. The interface
+ * major version is intended to change only when non backward compatible
+ * changes are made to the HWRM interface specification. A HWRM
+ * implementation that is compliant with this specification shall
+ * provide value of 1 in this field.
+ */
+ uint8_t hwrm_intf_min;
+ /*
+ * This field represents the minor version of HWRM interface
+ * specification supported by the HWRM implementation. A change in
+ * interface minor version is used to reflect significant backward
+ * compatible modification to HWRM interface specification. This can be
+ * due to addition or removal of functionality. HWRM interface
+ * specifications with the same major version but different minor
+ * versions are compatible. A HWRM implementation that is compliant with
+ * this specification shall provide value of 2 in this field.
+ */
+ uint8_t hwrm_intf_upd;
+ /*
+ * This field represents the update version of HWRM interface
+ * specification supported by the HWRM implementation. The interface
+ * update version is used to reflect minor changes or bug fixes to a
+ * released HWRM interface specification. A HWRM implementation that is
+ * compliant with this specification shall provide value of 2 in this
+ * field.
+ */
+ uint8_t hwrm_intf_rsvd;
+ uint8_t hwrm_fw_maj;
+ /*
+ * This field represents the major version of HWRM firmware. A change in
+ * firmware major version represents a major firmware release.
+ */
+ uint8_t hwrm_fw_min;
+ /*
+ * This field represents the minor version of HWRM firmware. A change in
+ * firmware minor version represents significant firmware functionality
+ * changes.
+ */
+ uint8_t hwrm_fw_bld;
+ /*
+ * This field represents the build version of HWRM firmware. A change in
+ * firmware build version represents bug fixes to a released firmware.
+ */
+ uint8_t hwrm_fw_rsvd;
+ /*
+ * This field is a reserved field. This field can be used to represent
+ * firmware branches or customer specific releases tied to a specific
+ * (major,minor,update) version of the HWRM firmware.
+ */
+ uint8_t mgmt_fw_maj;
+ /*
+ * This field represents the major version of mgmt firmware. A change in
+ * major version represents a major release.
+ */
+ uint8_t mgmt_fw_min;
+ /*
+ * This field represents the minor version of mgmt firmware. A change in
+ * minor version represents significant functionality changes.
+ */
+ uint8_t mgmt_fw_bld;
+ /*
+ * This field represents the build version of mgmt firmware. A change in
+ * update version represents bug fixes.
+ */
+ uint8_t mgmt_fw_rsvd;
+ /*
+ * This field is a reserved field. This field can be used to represent
+ * firmware branches or customer specific releases tied to a specific
+ * (major,minor,update) version
+ */
+ uint8_t netctrl_fw_maj;
+ /*
+ * This field represents the major version of network control firmware.
+ * A change in major version represents a major release.
+ */
+ uint8_t netctrl_fw_min;
+ /*
+ * This field represents the minor version of network control firmware.
+ * A change in minor version represents significant functionality
+ * changes.
+ */
+ uint8_t netctrl_fw_bld;
+ /*
+ * This field represents the build version of network control firmware.
+ * A change in update version represents bug fixes.
+ */
+ uint8_t netctrl_fw_rsvd;
+ /*
+ * This field is a reserved field. This field can be used to represent
+ * firmware branches or customer specific releases tied to a specific
+ * (major,minor,update) version
+ */
+ uint32_t reserved1;
+ /*
+ * This field is reserved for future use. The responder should set it to
+ * 0. The requester should ignore this field.
+ */
+ uint8_t roce_fw_maj;
+ /*
+ * This field represents the major version of RoCE firmware. A change in
+ * major version represents a major release.
+ */
+ uint8_t roce_fw_min;
+ /*
+ * This field represents the minor version of RoCE firmware. A change in
+ * minor version represents significant functionality changes.
+ */
+ uint8_t roce_fw_bld;
+ /*
+ * This field represents the build version of RoCE firmware. A change in
+ * update version represents bug fixes.
+ */
+ uint8_t roce_fw_rsvd;
+ /*
+ * This field is a reserved field. This field can be used to represent
+ * firmware branches or customer specific releases tied to a specific
+ * (major,minor,update) version
+ */
+ char hwrm_fw_name[16];
+ /*
+ * This field represents the name of HWRM FW (ASCII chars with NULL at
+ * the end).
+ */
+ char mgmt_fw_name[16];
+ /*
+ * This field represents the name of mgmt FW (ASCII chars with NULL at
+ * the end).
+ */
+ char netctrl_fw_name[16];
+ /*
+ * This field represents the name of network control firmware (ASCII
+ * chars with NULL at the end).
+ */
+ uint32_t reserved2[4];
+ /*
+ * This field is reserved for future use. The responder should set it to
+ * 0. The requester should ignore this field.
+ */
+ char roce_fw_name[16];
+ /*
+ * This field represents the name of RoCE FW (ASCII chars with NULL at
+ * the end).
+ */
+ uint16_t chip_num;
+ /* This field returns the chip number. */
+ uint8_t chip_rev;
+ /* This field returns the revision of chip. */
+ uint8_t chip_metal;
+ /* This field returns the chip metal number. */
+ uint8_t chip_bond_id;
+ /* This field returns the bond id of the chip. */
+ uint8_t chip_platform_type;
+ /*
+ * This value indicates the type of platform used for chip
+ * implementation.
+ */
+ /* ASIC */
+ #define HWRM_VER_GET_OUTPUT_CHIP_PLATFORM_TYPE_ASIC UINT32_C(0x0)
+ /* FPGA platform of the chip. */
+ #define HWRM_VER_GET_OUTPUT_CHIP_PLATFORM_TYPE_FPGA UINT32_C(0x1)
+ /* Palladium platform of the chip. */
+ #define HWRM_VER_GET_OUTPUT_CHIP_PLATFORM_TYPE_PALLADIUM UINT32_C(0x2)
+ uint16_t max_req_win_len;
+ /*
+ * This field returns the maximum value of request window that is
+ * supported by the HWRM. The request window is mapped into device
+ * address space using MMIO.
+ */
+ uint16_t max_resp_len;
+ /* This field returns the maximum value of response buffer in bytes. */
+ uint16_t def_req_timeout;
+ /* This field returns the default request timeout value in milliseconds. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_reset */
+/*
+ * Description: This command resets a hardware function (PCIe function) and
+ * frees any resources used by the function. This command shall be initiated by
+ * the driver after an FLR has occurred to prepare the function for re-use. This
+ * command may also be initiated by a driver prior to doing it's own
+ * configuration. This command puts the function into the reset state. In the
+ * reset state, global and port related features of the chip are not available.
+ */
+/*
+ * Note: This command will reset a function that has already been disabled or
+ * idled. The command returns all the resources owned by the function so a new
+ * driver may allocate and configure resources normally.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_reset_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the vf_id_valid field to be configured. */
+ #define HWRM_FUNC_RESET_INPUT_ENABLES_VF_ID_VALID UINT32_C(0x1)
+ uint16_t vf_id;
+ /*
+ * The ID of the VF that this PF is trying to reset. Only the parent PF
+ * shall be allowed to reset a child VF. A parent PF driver shall use
+ * this field only when a specific child VF is requested to be reset.
+ */
+ uint8_t func_reset_level;
+ /* This value indicates the level of a function reset. */
+ /*
+ * Reset the caller function and its children VFs (if any). If
+ * no children functions exist, then reset the caller function
+ * only.
+ */
+ #define HWRM_FUNC_RESET_INPUT_FUNC_RESET_LEVEL_RESETALL UINT32_C(0x0)
+ /* Reset the caller function only */
+ #define HWRM_FUNC_RESET_INPUT_FUNC_RESET_LEVEL_RESETME UINT32_C(0x1)
+ /*
+ * Reset all children VFs of the caller function driver if the
+ * caller is a PF driver. It is an error to specify this level
+ * by a VF driver. It is an error to specify this level by a PF
+ * driver with no children VFs.
+ */
+ #define HWRM_FUNC_RESET_INPUT_FUNC_RESET_LEVEL_RESETCHILDREN UINT32_C(0x2)
+ /*
+ * Reset a specific VF of the caller function driver if the
+ * caller is the parent PF driver. It is an error to specify
+ * this level by a VF driver. It is an error to specify this
+ * level by a PF driver that is not the parent of the VF that is
+ * being requested to reset.
+ */
+ #define HWRM_FUNC_RESET_INPUT_FUNC_RESET_LEVEL_RESETVF UINT32_C(0x3)
+ uint8_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_reset_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_getfid */
+/*
+ * Description: This command returns the FID value for the function. If a valid
+ * pci_id is provided, then this function returns fid for that PCI function.
+ * Otherwise, it returns FID of the requesting function. This value is needed to
+ * configure Rings and MSI-X vectors so their DMA operations appear correctly on
+ * the PCI bus. For PF-HWRM commands, there is no need for FID. Similarly there
+ * is no need for FID for VF-HWRM commands. In the PF-VF communication, only PF
+ * needs to know FIDs.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_getfid_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the pci_id field to be configured. */
+ #define HWRM_FUNC_GETFID_INPUT_ENABLES_PCI_ID UINT32_C(0x1)
+ uint16_t pci_id;
+ /*
+ * This value is the PCI ID of the queried function. If ARI is enabled,
+ * then it is Bus Number (8b):Function Number(8b). Otherwise, it is Bus
+ * Number (8b):Device Number (4b):Function Number(4b).
+ */
+ uint16_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_getfid_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t fid;
+ /*
+ * FID value. This value is used to identify operations on the PCI bus
+ * as belonging to a particular PCI function.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_vf_alloc */
+/*
+ * Description: This command is used to allocate requested number of virtual
+ * functions on a physical function. It will return the FID value of the first
+ * virtual function. The FIDs of the remaining virtual functions can be derived
+ * by sequentially incrementing the FID value of the first VF. This command
+ * supports the following models for VF allocation: # Allocation of one or more
+ * VFs from a PF without specifying the first VF ID # Allocation of multiple VFs
+ * from a PF starting with a specific VF # Allocation of a specific VF from a PF
+ * If this command is called on a virtual function or a physical function that
+ * is not enabled for SR-IOV, the HWRM shall return an error. The VF IDs
+ * returned by this function remain valid after the VF is disabled or reset.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_vf_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the first_vf_id field to be configured. */
+ #define HWRM_FUNC_VF_ALLOC_INPUT_ENABLES_FIRST_VF_ID UINT32_C(0x1)
+ uint16_t first_vf_id;
+ /*
+ * This value is used to identify a Virtual Function (VF). The scope of
+ * VF ID is local within a PF.
+ */
+ uint16_t num_vfs;
+ /* The number of virtual functions requested. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_vf_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t first_vf_id;
+ /* The ID of the first VF allocated. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_vf_free */
+/*
+ * Description: This command will free allocated virtual functions on a physical
+ * function. If this command is called on a virtual function or a physical
+ * function that is not enabled for SR-IOV, the HWRM shall return an error.
+ * After the successful completion of this command, the VF IDs of the VFs that
+ * are freed on the PF are invalid.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_vf_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the first_vf_id field to be configured. */
+ #define HWRM_FUNC_VF_FREE_INPUT_ENABLES_FIRST_VF_ID UINT32_C(0x1)
+ uint16_t first_vf_id;
+ /*
+ * This value is used to identify a Virtual Function (VF). The scope of
+ * VF ID is local within a PF.
+ */
+ uint16_t num_vfs;
+ /*
+ * The number of virtual functions requested. 0xFFFF - Cleanup all
+ * children of this PF.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_vf_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_vf_cfg */
+/*
+ * Description: This command allows configuration of a VF by its driver. If this
+ * function is called by a PF driver, then the HWRM shall fail this command. If
+ * guest VLAN and/or MAC address are provided in this command, then the HWRM
+ * shall set up appropriate MAC/VLAN filters for the VF that is being
+ * configured. A VF driver should set VF MTU/MRU using this command prior to
+ * allocating RX VNICs or TX rings for the corresponding VF.
+ */
+/* Input (32 bytes) */
+
+struct hwrm_func_vf_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the mtu field to be configured. */
+ #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_MTU UINT32_C(0x1)
+ /* This bit must be '1' for the guest_vlan field to be configured. */
+ #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_GUEST_VLAN UINT32_C(0x2)
+ /* This bit must be '1' for the async_event_cr field to be configured. */
+ #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR UINT32_C(0x4)
+ /* This bit must be '1' for the dflt_mac_addr field to be configured. */
+ #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_DFLT_MAC_ADDR UINT32_C(0x8)
+ uint16_t mtu;
+ /*
+ * The maximum transmission unit requested on the function. The HWRM
+ * should make sure that the mtu of the function does not exceed the mtu
+ * of the physical port that this function is associated with. In
+ * addition to requesting mtu per function, it is possible to configure
+ * mtu per transmit ring. By default, the mtu of each transmit ring
+ * associated with a function is equal to the mtu of the function. The
+ * HWRM should make sure that the mtu of each transmit ring that is
+ * assigned to a function has a valid mtu.
+ */
+ uint16_t guest_vlan;
+ /*
+ * The guest VLAN for the function being configured. This field's format
+ * is same as 802.1Q Tag's Tag Control Information (TCI) format that
+ * includes both Priority Code Point (PCP) and VLAN Identifier (VID).
+ */
+ uint16_t async_event_cr;
+ /*
+ * ID of the target completion ring for receiving asynchronous event
+ * completions. If this field is not valid, then the HWRM shall use the
+ * default completion ring of the function that is being configured as
+ * the target completion ring for providing any asynchronous event
+ * completions for that function. If this field is valid, then the HWRM
+ * shall use the completion ring identified by this ID as the target
+ * completion ring for providing any asynchronous event completions for
+ * the function that is being configured.
+ */
+ uint8_t dflt_mac_addr[6];
+ /*
+ * This value is the current MAC address requested by the VF driver to
+ * be configured on this VF. A value of 00-00-00-00-00-00 indicates no
+ * MAC address configuration is requested by the VF driver. The parent
+ * PF driver may reject or overwrite this MAC address.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_vf_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_qcaps */
+/*
+ * Description: This command returns capabilities of a function. The input FID
+ * value is used to indicate what function is being queried. This allows a
+ * physical function driver to query virtual functions that are children of the
+ * physical function. The output FID value is needed to configure Rings and
+ * MSI-X vectors so their DMA operations appear correctly on the PCI bus.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_qcaps_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t fid;
+ /*
+ * Function ID of the function that is being queried. 0xFF... (All Fs)
+ * if the query is for the requesting function.
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (80 bytes) */
+
+struct hwrm_func_qcaps_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t fid;
+ /*
+ * FID value. This value is used to identify operations on the PCI bus
+ * as belonging to a particular PCI function.
+ */
+ uint16_t port_id;
+ /*
+ * Port ID of port that this function is associated with. Valid only for
+ * the PF. 0xFF... (All Fs) if this function is not associated with any
+ * port. 0xFF... (All Fs) if this function is called from a VF.
+ */
+ uint32_t flags;
+ /* If 1, then Push mode is supported on this function. */
+ #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_PUSH_MODE_SUPPORTED UINT32_C(0x1)
+ /* If 1, then the global MSI-X auto-masking is enabled for the device. */
+ #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_GLOBAL_MSIX_AUTOMASKING UINT32_C(0x2)
+ /*
+ * If 1, then the Precision Time Protocol (PTP) processing is supported
+ * on this function. The HWRM should enable PTP on only a single
+ * Physical Function (PF) per port.
+ */
+ #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_PTP_SUPPORTED UINT32_C(0x4)
+ /*
+ * If 1, then RDMA over Converged Ethernet (RoCE) v1 is supported on
+ * this function.
+ */
+ #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ROCE_V1_SUPPORTED UINT32_C(0x8)
+ /*
+ * If 1, then RDMA over Converged Ethernet (RoCE) v2 is supported on
+ * this function.
+ */
+ #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ROCE_V2_SUPPORTED UINT32_C(0x10)
+ /*
+ * If 1, then control and configuration of WoL magic packet is supported
+ * on this function.
+ */
+ #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED UINT32_C(0x20)
+ /*
+ * If 1, then control and configuration of bitmap pattern packet is
+ * supported on this function.
+ */
+ #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_BMP_SUPPORTED UINT32_C(0x40)
+ uint8_t mac_address[6];
+ /*
+ * This value is current MAC address configured for this function. A
+ * value of 00-00-00-00-00-00 indicates no MAC address is currently
+ * configured.
+ */
+ uint16_t max_rsscos_ctx;
+ /*
+ * The maximum number of RSS/COS contexts that can be allocated to the
+ * function.
+ */
+ uint16_t max_cmpl_rings;
+ /*
+ * The maximum number of completion rings that can be allocated to the
+ * function.
+ */
+ uint16_t max_tx_rings;
+ /*
+ * The maximum number of transmit rings that can be allocated to the
+ * function.
+ */
+ uint16_t max_rx_rings;
+ /*
+ * The maximum number of receive rings that can be allocated to the
+ * function.
+ */
+ uint16_t max_l2_ctxs;
+ /*
+ * The maximum number of L2 contexts that can be allocated to the
+ * function.
+ */
+ uint16_t max_vnics;
+ /* The maximum number of VNICs that can be allocated to the function. */
+ uint16_t first_vf_id;
+ /*
+ * The identifier for the first VF enabled on a PF. This is valid only
+ * on the PF with SR-IOV enabled. 0xFF... (All Fs) if this command is
+ * called on a PF with SR-IOV disabled or on a VF.
+ */
+ uint16_t max_vfs;
+ /*
+ * The maximum number of VFs that can be allocated to the function. This
+ * is valid only on the PF with SR-IOV enabled. 0xFF... (All Fs) if this
+ * command is called on a PF with SR-IOV disabled or on a VF.
+ */
+ uint16_t max_stat_ctx;
+ /*
+ * The maximum number of statistic contexts that can be allocated to the
+ * function.
+ */
+ uint32_t max_encap_records;
+ /*
+ * The maximum number of Encapsulation records that can be offloaded by
+ * this function.
+ */
+ uint32_t max_decap_records;
+ /*
+ * The maximum number of decapsulation records that can be offloaded by
+ * this function.
+ */
+ uint32_t max_tx_em_flows;
+ /*
+ * The maximum number of Exact Match (EM) flows that can be offloaded by
+ * this function on the TX side.
+ */
+ uint32_t max_tx_wm_flows;
+ /*
+ * The maximum number of Wildcard Match (WM) flows that can be offloaded
+ * by this function on the TX side.
+ */
+ uint32_t max_rx_em_flows;
+ /*
+ * The maximum number of Exact Match (EM) flows that can be offloaded by
+ * this function on the RX side.
+ */
+ uint32_t max_rx_wm_flows;
+ /*
+ * The maximum number of Wildcard Match (WM) flows that can be offloaded
+ * by this function on the RX side.
+ */
+ uint32_t max_mcast_filters;
+ /*
+ * The maximum number of multicast filters that can be supported by this
+ * function on the RX side.
+ */
+ uint32_t max_flow_id;
+ /*
+ * The maximum value of flow_id that can be supported in completion
+ * records.
+ */
+ uint32_t max_hw_ring_grps;
+ /*
+ * The maximum number of HW ring groups that can be supported on this
+ * function.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_qcfg */
+/*
+ * Description: This command returns the current configuration of a function.
+ * The input FID value is used to indicate what function is being queried. This
+ * allows a physical function driver to query virtual functions that are
+ * children of the physical function. The output FID value is needed to
+ * configure Rings and MSI-X vectors so their DMA operations appear correctly on
+ * the PCI bus.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t fid;
+ /*
+ * Function ID of the function that is being queried. 0xFF... (All Fs)
+ * if the query is for the requesting function.
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (72 bytes) */
+
+struct hwrm_func_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t fid;
+ /*
+ * FID value. This value is used to identify operations on the PCI bus
+ * as belonging to a particular PCI function.
+ */
+ uint16_t port_id;
+ /*
+ * Port ID of port that this function is associated with. 0xFF... (All
+ * Fs) if this function is not associated with any port.
+ */
+ uint16_t vlan;
+ /*
+ * This value is the current VLAN setting for this function. The value
+ * of 0 for this field indicates no priority tagging or VLAN is used.
+ * This field's format is same as 802.1Q Tag's Tag Control Information
+ * (TCI) format that includes both Priority Code Point (PCP) and VLAN
+ * Identifier (VID).
+ */
+ uint16_t flags;
+ /*
+ * If 1, then magic packet based Out-Of-Box WoL is enabled on the port
+ * associated with this function.
+ */
+ #define HWRM_FUNC_QCFG_OUTPUT_FLAGS_OOB_WOL_MAGICPKT_ENABLED UINT32_C(0x1)
+ /*
+ * If 1, then bitmap pattern based Out-Of-Box WoL packet is enabled on
+ * the port associated with this function.
+ */
+ #define HWRM_FUNC_QCFG_OUTPUT_FLAGS_OOB_WOL_BMP_ENABLED UINT32_C(0x2)
+ uint8_t mac_address[6];
+ /*
+ * This value is current MAC address configured for this function. A
+ * value of 00-00-00-00-00-00 indicates no MAC address is currently
+ * configured.
+ */
+ uint16_t pci_id;
+ /*
+ * This value is current PCI ID of this function. If ARI is enabled,
+ * then it is Bus Number (8b):Function Number(8b). Otherwise, it is Bus
+ * Number (8b):Device Number (4b):Function Number(4b).
+ */
+ uint16_t alloc_rsscos_ctx;
+ /* The number of RSS/COS contexts currently allocated to the function. */
+ uint16_t alloc_cmpl_rings;
+ /*
+ * The number of completion rings currently allocated to the function.
+ * This does not include the rings allocated to any children functions
+ * if any.
+ */
+ uint16_t alloc_tx_rings;
+ /*
+ * The number of transmit rings currently allocated to the function.
+ * This does not include the rings allocated to any children functions
+ * if any.
+ */
+ uint16_t alloc_rx_rings;
+ /*
+ * The number of receive rings currently allocated to the function. This
+ * does not include the rings allocated to any children functions if
+ * any.
+ */
+ uint16_t alloc_l2_ctx;
+ /* The allocated number of L2 contexts to the function. */
+ uint16_t alloc_vnics;
+ /* The allocated number of vnics to the function. */
+ uint16_t mtu;
+ /*
+ * The maximum transmission unit of the function. For rings allocated on
+ * this function, this default value is used if ring MTU is not
+ * specified.
+ */
+ uint16_t mru;
+ /*
+ * The maximum receive unit of the function. For vnics allocated on this
+ * function, this default value is used if vnic MRU is not specified.
+ */
+ uint16_t stat_ctx_id;
+ /* The statistics context assigned to a function. */
+ uint8_t port_partition_type;
+ /*
+ * The HWRM shall return Unknown value for this field when this command
+ * is used to query VF's configuration.
+ */
+ /* Single physical function */
+ #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_SPF UINT32_C(0x0)
+ /* Multiple physical functions */
+ #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_MPFS UINT32_C(0x1)
+ /* Network Partitioning 1.0 */
+ #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_0 UINT32_C(0x2)
+ /* Network Partitioning 1.5 */
+ #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_5 UINT32_C(0x3)
+ /* Network Partitioning 2.0 */
+ #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR2_0 UINT32_C(0x4)
+ /* Unknown */
+ #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_UNKNOWN UINT32_C(0xff)
+ uint8_t unused_0;
+ uint16_t dflt_vnic_id;
+ /* The default VNIC ID assigned to a function that is being queried. */
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint32_t min_bw;
+ /*
+ * Minimum BW allocated for this function in Mbps. The HWRM will
+ * translate this value into byte counter and time interval used for the
+ * scheduler inside the device. A value of 0 indicates the minimum
+ * bandwidth is not configured.
+ */
+ uint32_t max_bw;
+ /*
+ * Maximum BW allocated for this function in Mbps. The HWRM will
+ * translate this value into byte counter and time interval used for the
+ * scheduler inside the device. A value of 0 indicates that the maximum
+ * bandwidth is not configured.
+ */
+ uint8_t evb_mode;
+ /*
+ * This value indicates the Edge virtual bridge mode for the domain that
+ * this function belongs to.
+ */
+ /* No Edge Virtual Bridging (EVB) */
+ #define HWRM_FUNC_QCFG_OUTPUT_EVB_MODE_NO_EVB UINT32_C(0x0)
+ /* Virtual Ethernet Bridge (VEB) */
+ #define HWRM_FUNC_QCFG_OUTPUT_EVB_MODE_VEB UINT32_C(0x1)
+ /* Virtual Ethernet Port Aggregator (VEPA) */
+ #define HWRM_FUNC_QCFG_OUTPUT_EVB_MODE_VEPA UINT32_C(0x2)
+ uint8_t unused_3;
+ uint16_t unused_4;
+ uint32_t alloc_mcast_filters;
+ /*
+ * The number of allocated multicast filters for this function on the RX
+ * side.
+ */
+ uint32_t alloc_hw_ring_grps;
+ /* The number of allocated HW ring groups for this function. */
+ uint8_t unused_5;
+ uint8_t unused_6;
+ uint8_t unused_7;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_cfg */
+/*
+ * Description: This command allows configuration of a PF by the corresponding
+ * PF driver. This command also allows configuration of a child VF by its parent
+ * PF driver. The input FID value is used to indicate what function is being
+ * configured. This allows a PF driver to configure the PF owned by itself or a
+ * virtual function that is a child of the PF. This command allows to reserve
+ * resources for a VF by its parent PF. To reverse the process, the command
+ * should be called with all enables flags cleared for resources. This will free
+ * allocated resources for the VF and return them to the resource pool. If this
+ * command is requested by a VF driver to configure or reserve resources, then
+ * the HWRM shall fail this command. If default MAC address and/or VLAN are
+ * provided in this command, then the HWRM shall set up appropriate MAC/VLAN
+ * filters for the function that is being configured. If source properties
+ * checks are enabled and default MAC address and/or IP address are provided in
+ * this command, then the HWRM shall set appropriate source property checks
+ * based on provided MAC and/or IP addresses. The parent PF driver should not
+ * set MTU/MRU for a VF using this command. This is to allow MTU/MRU setting by
+ * the VF driver. If the MTU or MRU for a VF is set by the PF driver, then the
+ * HWRM should ignore it. A function's MTU/MRU should be set prior to allocating
+ * RX VNICs or TX rings.
+ */
+/* Input (88 bytes) */
+
+struct hwrm_func_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t fid;
+ /*
+ * Function ID of the function that is being configured. If set to
+ * 0xFF... (All Fs), then the the configuration is for the requesting
+ * function.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint32_t flags;
+ /*
+ * When this bit is '1', the function is requested to be put in the
+ * promiscuous mode.
+ */
+ #define HWRM_FUNC_CFG_INPUT_FLAGS_PROM_MODE UINT32_C(0x1)
+ /*
+ * When this bit is '1', the function is enabled with source MAC address
+ * check. This is an anti-spoofing check. If this flag is set, then the
+ * function shall be configured to allow transmission of frames with the
+ * source MAC address that is configured for this function.
+ */
+ #define HWRM_FUNC_CFG_INPUT_FLAGS_SRC_MAC_ADDR_CHECK UINT32_C(0x2)
+ /*
+ * When this bit is '1', the function is enabled with source IP address
+ * check. This is an anti-spoofing check. If this flag is set, then the
+ * function shall be configured to allow transmission of frames with the
+ * source IP address that is configured for this function.
+ */
+ #define HWRM_FUNC_CFG_INPUT_FLAGS_SRC_IP_ADDR_CHECK UINT32_C(0x4)
+ /*
+ * When this bit is set to '1', the function shall be configured with
+ * VLAN priority match. If the VLAN PRI of a packet originated from this
+ * function does not match, then the packet shall be discarded.
+ */
+ #define HWRM_FUNC_CFG_INPUT_FLAGS_VLAN_PRI_MATCH UINT32_C(0x8)
+ /*
+ * When this bit is set to '1', the function shall be configured to
+ * check for VLAN priority match. If the VLAN PRI of a packet originated
+ * from this function does not match, then the default VLAN PRI shall be
+ * used.
+ */
+ #define HWRM_FUNC_CFG_INPUT_FLAGS_DFLT_PRI_NOMATCH UINT32_C(0x10)
+ /*
+ * When this bit is set to '1', the function shall be configured to not
+ * allow the transmission of pause frames. PAUSE frames use 48-bit
+ * destination multicast MAC address 01-80-C2-00-00-01.
+ */
+ #define HWRM_FUNC_CFG_INPUT_FLAGS_DISABLE_PAUSE UINT32_C(0x20)
+ /*
+ * When this bit is set to '1', the function shall be configured to not
+ * allow the transmission of Spanning Tree Protocol (STP) frames. STP
+ * frames use Ethertype 0x0802 and 48-bit destination multicast MAC
+ * address 01-80-C2-00-00-00 and 01-80-C2-00-00-08 for 802.1D and
+ * 802.1ad respectively.
+ */
+ #define HWRM_FUNC_CFG_INPUT_FLAGS_DISABLE_STP UINT32_C(0x40)
+ /*
+ * When this bit is set to '1', the function shall be configured to not
+ * allow the transmission of Link Layer Discovery Protocol (LLDP)
+ * frames. LLDP frames use Ethertype 0x88CC and 48-bit destination
+ * multicast MAC address 01-80-C2-00-00-00 or 01-80-C2-00-00-03 or
+ * 01-80-C2-00-00-0E.
+ */
+ #define HWRM_FUNC_CFG_INPUT_FLAGS_DISABLE_LLDP UINT32_C(0x80)
+ /*
+ * When this bit is set to '1', the function shall be configured to not
+ * allow the transmission of Precision Time Protocol (PTP) v2 frames.
+ * PTP frames use Ethertype 0x88F7 and 48-bit destination multicast MAC
+ * address 01-80-C2-00-00-0E or 01-1B-19-00-00-00.
+ */
+ #define HWRM_FUNC_CFG_INPUT_FLAGS_DISABLE_PTPV2 UINT32_C(0x100)
+ uint32_t enables;
+ /* This bit must be '1' for the mtu field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_MTU UINT32_C(0x1)
+ /* This bit must be '1' for the mru field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_MRU UINT32_C(0x2)
+ /* This bit must be '1' for the num_rsscos_ctxs field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RSSCOS_CTXS UINT32_C(0x4)
+ /* This bit must be '1' for the num_cmpl_rings field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_CMPL_RINGS UINT32_C(0x8)
+ /* This bit must be '1' for the num_tx_rings field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_TX_RINGS UINT32_C(0x10)
+ /* This bit must be '1' for the num_rx_rings field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RX_RINGS UINT32_C(0x20)
+ /* This bit must be '1' for the num_l2_ctxs field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_L2_CTXS UINT32_C(0x40)
+ /* This bit must be '1' for the num_vnics field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_VNICS UINT32_C(0x80)
+ /* This bit must be '1' for the num_stat_ctxs field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_STAT_CTXS UINT32_C(0x100)
+ /* This bit must be '1' for the dflt_mac_addr field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_DFLT_MAC_ADDR UINT32_C(0x200)
+ /* This bit must be '1' for the dflt_vlan field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_DFLT_VLAN UINT32_C(0x400)
+ /* This bit must be '1' for the dflt_ip_addr field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_DFLT_IP_ADDR UINT32_C(0x800)
+ /* This bit must be '1' for the min_bw field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_MIN_BW UINT32_C(0x1000)
+ /* This bit must be '1' for the max_bw field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_MAX_BW UINT32_C(0x2000)
+ /* This bit must be '1' for the async_event_cr field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR UINT32_C(0x4000)
+ /*
+ * This bit must be '1' for the vlan_antispoof_mode field to be
+ * configured.
+ */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_VLAN_ANTISPOOF_MODE UINT32_C(0x8000)
+ /*
+ * This bit must be '1' for the allowed_vlan_pris field to be
+ * configured.
+ */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_ALLOWED_VLAN_PRIS UINT32_C(0x10000)
+ /* This bit must be '1' for the evb_mode field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_EVB_MODE UINT32_C(0x20000)
+ /*
+ * This bit must be '1' for the num_mcast_filters field to be
+ * configured.
+ */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_MCAST_FILTERS UINT32_C(0x40000)
+ /* This bit must be '1' for the num_hw_ring_grps field to be configured. */
+ #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_HW_RING_GRPS UINT32_C(0x80000)
+ uint16_t mtu;
+ /*
+ * The maximum transmission unit of the function. The HWRM should make
+ * sure that the mtu of the function does not exceed the mtu of the
+ * physical port that this function is associated with. In addition to
+ * configuring mtu per function, it is possible to configure mtu per
+ * transmit ring. By default, the mtu of each transmit ring associated
+ * with a function is equal to the mtu of the function. The HWRM should
+ * make sure that the mtu of each transmit ring that is assigned to a
+ * function has a valid mtu.
+ */
+ uint16_t mru;
+ /*
+ * The maximum receive unit of the function. The HWRM should make sure
+ * that the mru of the function does not exceed the mru of the physical
+ * port that this function is associated with. In addition to
+ * configuring mru per function, it is possible to configure mru per
+ * vnic. By default, the mru of each vnic associated with a function is
+ * equal to the mru of the function. The HWRM should make sure that the
+ * mru of each vnic that is assigned to a function has a valid mru.
+ */
+ uint16_t num_rsscos_ctxs;
+ /* The number of RSS/COS contexts requested for the function. */
+ uint16_t num_cmpl_rings;
+ /*
+ * The number of completion rings requested for the function. This does
+ * not include the rings allocated to any children functions if any.
+ */
+ uint16_t num_tx_rings;
+ /*
+ * The number of transmit rings requested for the function. This does
+ * not include the rings allocated to any children functions if any.
+ */
+ uint16_t num_rx_rings;
+ /*
+ * The number of receive rings requested for the function. This does not
+ * include the rings allocated to any children functions if any.
+ */
+ uint16_t num_l2_ctxs;
+ /* The requested number of L2 contexts for the function. */
+ uint16_t num_vnics;
+ /* The requested number of vnics for the function. */
+ uint16_t num_stat_ctxs;
+ /* The requested number of statistic contexts for the function. */
+ uint16_t num_hw_ring_grps;
+ /*
+ * The number of HW ring groups that should be reserved for this
+ * function.
+ */
+ uint8_t dflt_mac_addr[6];
+ /* The default MAC address for the function being configured. */
+ uint16_t dflt_vlan;
+ /*
+ * The default VLAN for the function being configured. This field's
+ * format is same as 802.1Q Tag's Tag Control Information (TCI) format
+ * that includes both Priority Code Point (PCP) and VLAN Identifier
+ * (VID).
+ */
+ uint32_t dflt_ip_addr[4]; /* big endian */
+ /*
+ * The default IP address for the function being configured. This
+ * address is only used in enabling source property check.
+ */
+ uint32_t min_bw;
+ /*
+ * Minimum BW allocated for this function in Mbps. The HWRM will
+ * translate this value into byte counter and time interval used for the
+ * scheduler inside the device.
+ */
+ uint32_t max_bw;
+ /*
+ * Maximum BW allocated for this function in Mbps. The HWRM will
+ * translate this value into byte counter and time interval used for the
+ * scheduler inside the device.
+ */
+ uint16_t async_event_cr;
+ /*
+ * ID of the target completion ring for receiving asynchronous event
+ * completions. If this field is not valid, then the HWRM shall use the
+ * default completion ring of the function that is being configured as
+ * the target completion ring for providing any asynchronous event
+ * completions for that function. If this field is valid, then the HWRM
+ * shall use the completion ring identified by this ID as the target
+ * completion ring for providing any asynchronous event completions for
+ * the function that is being configured.
+ */
+ uint8_t vlan_antispoof_mode;
+ /* VLAN Anti-spoofing mode. */
+ /* No VLAN anti-spoofing checks are enabled */
+ #define HWRM_FUNC_CFG_INPUT_VLAN_ANTISPOOF_MODE_NOCHECK UINT32_C(0x0)
+ /* Validate VLAN against the configured VLAN(s) */
+ #define HWRM_FUNC_CFG_INPUT_VLAN_ANTISPOOF_MODE_VALIDATE_VLAN UINT32_C(0x1)
+ /* Insert VLAN if it does not exist, otherwise discard */
+ #define HWRM_FUNC_CFG_INPUT_VLAN_ANTISPOOF_MODE_INSERT_IF_VLANDNE UINT32_C(0x2)
+ /* Insert VLAN if it does not exist, override VLAN if it exists */
+ #define HWRM_FUNC_CFG_INPUT_VLAN_ANTISPOOF_MODE_INSERT_OR_OVERRIDE_VLAN UINT32_C(0x3)
+ uint8_t allowed_vlan_pris;
+ /*
+ * This bit field defines VLAN PRIs that are allowed on this function.
+ * If nth bit is set, then VLAN PRI n is allowed on this function.
+ */
+ uint8_t evb_mode;
+ /*
+ * The HWRM shall allow a PF driver to change EVB mode for the partition
+ * it belongs to. The HWRM shall not allow a VF driver to change the EVB
+ * mode. The HWRM shall take into account the switching of EVB mode from
+ * one to another and reconfigure hardware resources as appropriately.
+ * The switching from VEB to VEPA mode requires the disabling of the
+ * loopback traffic. Additionally, source knock outs are handled
+ * differently in VEB and VEPA modes.
+ */
+ /* No Edge Virtual Bridging (EVB) */
+ #define HWRM_FUNC_CFG_INPUT_EVB_MODE_NO_EVB UINT32_C(0x0)
+ /* Virtual Ethernet Bridge (VEB) */
+ #define HWRM_FUNC_CFG_INPUT_EVB_MODE_VEB UINT32_C(0x1)
+ /* Virtual Ethernet Port Aggregator (VEPA) */
+ #define HWRM_FUNC_CFG_INPUT_EVB_MODE_VEPA UINT32_C(0x2)
+ uint8_t unused_2;
+ uint16_t num_mcast_filters;
+ /*
+ * The number of multicast filters that should be reserved for this
+ * function on the RX side.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_qstats */
+/*
+ * Description: This command returns statistics of a function. The input FID
+ * value is used to indicate what function is being queried. This allows a
+ * physical function driver to query virtual functions that are children of the
+ * physical function. The HWRM shall return any unsupported counter with a value
+ * of 0xFFFFFFFF for 32-bit counters and 0xFFFFFFFFFFFFFFFF for 64-bit counters.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_qstats_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t fid;
+ /*
+ * Function ID of the function that is being queried. 0xFF... (All Fs)
+ * if the query is for the requesting function.
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (176 bytes) */
+
+struct hwrm_func_qstats_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint64_t tx_ucast_pkts;
+ /* Number of transmitted unicast packets on the function. */
+ uint64_t tx_mcast_pkts;
+ /* Number of transmitted multicast packets on the function. */
+ uint64_t tx_bcast_pkts;
+ /* Number of transmitted broadcast packets on the function. */
+ uint64_t tx_err_pkts;
+ /*
+ * Number of transmitted packets that were dropped due to internal NIC
+ * resource problems. For transmit, this can only happen if TMP is
+ * configured to allow dropping in HOL blocking conditions, which is not
+ * a normal configuration.
+ */
+ uint64_t tx_drop_pkts;
+ /*
+ * Number of dropped packets on transmit path on the function. These are
+ * packets that have been marked for drop by the TE CFA block or are
+ * packets that exceeded the transmit MTU limit for the function.
+ */
+ uint64_t tx_ucast_bytes;
+ /* Number of transmitted bytes for unicast traffic on the function. */
+ uint64_t tx_mcast_bytes;
+ /* Number of transmitted bytes for multicast traffic on the function. */
+ uint64_t tx_bcast_bytes;
+ /* Number of transmitted bytes for broadcast traffic on the function. */
+ uint64_t rx_ucast_pkts;
+ /* Number of received unicast packets on the function. */
+ uint64_t rx_mcast_pkts;
+ /* Number of received multicast packets on the function. */
+ uint64_t rx_bcast_pkts;
+ /* Number of received broadcast packets on the function. */
+ uint64_t rx_err_pkts;
+ /*
+ * Number of received packets that were dropped on the function due to
+ * resource limitations. This can happen for 3 reasons. # The BD used
+ * for the packet has a bad format. # There were no BDs available in the
+ * ring for the packet. # There were no BDs available on-chip for the
+ * packet.
+ */
+ uint64_t rx_drop_pkts;
+ /*
+ * Number of dropped packets on received path on the function. These are
+ * packets that have been marked for drop by the RE CFA.
+ */
+ uint64_t rx_ucast_bytes;
+ /* Number of received bytes for unicast traffic on the function. */
+ uint64_t rx_mcast_bytes;
+ /* Number of received bytes for multicast traffic on the function. */
+ uint64_t rx_bcast_bytes;
+ /* Number of received bytes for broadcast traffic on the function. */
+ uint64_t rx_agg_pkts;
+ /* Number of aggregated unicast packets on the function. */
+ uint64_t rx_agg_bytes;
+ /* Number of aggregated unicast bytes on the function. */
+ uint64_t rx_agg_events;
+ /* Number of aggregation events on the function. */
+ uint64_t rx_agg_aborts;
+ /* Number of aborted aggregations on the function. */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_clr_stats */
+/*
+ * Description: This command clears statistics of a function. The input FID
+ * value is used to indicate what function's statistics is being cleared. This
+ * allows a physical function driver to clear statistics of virtual functions
+ * that are children of the physical function.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_clr_stats_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t fid;
+ /*
+ * Function ID of the function. 0xFF... (All Fs) if the query is for the
+ * requesting function.
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_clr_stats_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_vf_resc_free */
+/* Description: This command frees resources of a vf. */
+/* Input (24 bytes) */
+
+struct hwrm_func_vf_resc_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t vf_id;
+ /*
+ * This value is used to identify a Virtual Function (VF). The scope of
+ * VF ID is local within a PF.
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_vf_resc_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_vf_vnic_ids_query */
+/* Description: This command is used to query vf vnic ids. */
+/* Input (32 bytes) */
+
+struct hwrm_func_vf_vnic_ids_query_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t vf_id;
+ /*
+ * This value is used to identify a Virtual Function (VF). The scope of
+ * VF ID is local within a PF.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint32_t max_vnic_id_cnt;
+ /* Max number of vnic ids in vnic id table */
+ uint64_t vnic_id_tbl_addr;
+ /* This is the address for VF VNIC ID table */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_vf_vnic_ids_query_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t vnic_id_cnt;
+ /* Actual number of vnic ids Each VNIC ID is written as a 32-bit number. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_drv_rgtr */
+/*
+ * Description: This command is used by the function driver to register its
+ * information with the HWRM. A function driver shall implement this command. A
+ * function driver shall use this command during the driver initialization right
+ * after the HWRM version discovery and default ring resources allocation.
+ */
+/* Input (80 bytes) */
+
+struct hwrm_func_drv_rgtr_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * When this bit is '1', the function driver is requesting all requests
+ * from its children VF drivers to be forwarded to itself. This flag can
+ * only be set by the PF driver. If a VF driver sets this flag, it
+ * should be ignored by the HWRM.
+ */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FWD_ALL_MODE UINT32_C(0x1)
+ /*
+ * When this bit is '1', the function is requesting none of the requests
+ * from its children VF drivers to be forwarded to itself. This flag can
+ * only be set by the PF driver. If a VF driver sets this flag, it
+ * should be ignored by the HWRM.
+ */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FWD_NONE_MODE UINT32_C(0x2)
+ uint32_t enables;
+ /* This bit must be '1' for the os_type field to be configured. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE UINT32_C(0x1)
+ /* This bit must be '1' for the ver field to be configured. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER UINT32_C(0x2)
+ /* This bit must be '1' for the timestamp field to be configured. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_TIMESTAMP UINT32_C(0x4)
+ /* This bit must be '1' for the vf_req_fwd field to be configured. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VF_REQ_FWD UINT32_C(0x8)
+ /* This bit must be '1' for the async_event_fwd field to be configured. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD UINT32_C(0x10)
+ uint16_t os_type;
+ /* This value indicates the type of OS. */
+ /* Unknown */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_UNKNOWN UINT32_C(0x0)
+ /* Other OS not listed below. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_OTHER UINT32_C(0x1)
+ /* MSDOS OS. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_MSDOS UINT32_C(0xe)
+ /* Windows OS. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_WINDOWS UINT32_C(0x12)
+ /* Solaris OS. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_SOLARIS UINT32_C(0x1d)
+ /* Linux OS. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_LINUX UINT32_C(0x24)
+ /* FreeBSD OS. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD UINT32_C(0x2a)
+ /* VMware ESXi OS. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_ESXI UINT32_C(0x68)
+ /* Microsoft Windows 8 64-bit OS. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_WIN864 UINT32_C(0x73)
+ /* Microsoft Windows Server 2012 R2 OS. */
+ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_WIN2012R2 UINT32_C(0x74)
+ uint8_t ver_maj;
+ /* This is the major version of the driver. */
+ uint8_t ver_min;
+ /* This is the minor version of the driver. */
+ uint8_t ver_upd;
+ /* This is the update version of the driver. */
+ uint8_t unused_0;
+ uint16_t unused_1;
+ uint32_t timestamp;
+ /*
+ * This is a 32-bit timestamp provided by the driver for keep alive. The
+ * timestamp is in multiples of 1ms.
+ */
+ uint32_t unused_2;
+ uint32_t vf_req_fwd[8];
+ /*
+ * This is a 256-bit bit mask provided by the PF driver for letting the
+ * HWRM know what commands issued by the VF driver to the HWRM should be
+ * forwarded to the PF driver. Nth bit refers to the Nth req_type.
+ * Setting Nth bit to 1 indicates that requests from the VF driver with
+ * req_type equal to N shall be forwarded to the parent PF driver. This
+ * field is not valid for the VF driver.
+ */
+ uint32_t async_event_fwd[8];
+ /*
+ * This is a 256-bit bit mask provided by the function driver (PF or VF
+ * driver) to indicate the list of asynchronous event completions to be
+ * forwarded. Nth bit refers to the Nth event_id. Setting Nth bit to 1
+ * by the function driver shall result in the HWRM forwarding
+ * asynchronous event completion with event_id equal to N. If all bits
+ * are set to 0 (value of 0), then the HWRM shall not forward any
+ * asynchronous event completion to this function driver.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_drv_rgtr_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_drv_unrgtr */
+/*
+ * Description: This command is used by the function driver to un register with
+ * the HWRM. A function driver shall implement this command. A function driver
+ * shall use this command during the driver unloading.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_drv_unrgtr_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * When this bit is '1', the function driver is notifying the HWRM to
+ * prepare for the shutdown.
+ */
+ #define HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN UINT32_C(0x1)
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_drv_unrgtr_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_buf_rgtr */
+/*
+ * Description: This command is used by the PF driver to register buffers used
+ * in the PF-VF communication with the HWRM. The PF driver uses this command to
+ * register buffers for each PF-VF channel. A parent PF may issue this command
+ * per child VF. If VF ID is not valid, then this command is used to register
+ * buffers for all children VFs of the PF.
+ */
+/* Input (128 bytes) */
+
+struct hwrm_func_buf_rgtr_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the vf_id field to be configured. */
+ #define HWRM_FUNC_BUF_RGTR_INPUT_ENABLES_VF_ID UINT32_C(0x1)
+ /* This bit must be '1' for the err_buf_addr field to be configured. */
+ #define HWRM_FUNC_BUF_RGTR_INPUT_ENABLES_ERR_BUF_ADDR UINT32_C(0x2)
+ uint16_t vf_id;
+ /*
+ * This value is used to identify a Virtual Function (VF). The scope of
+ * VF ID is local within a PF.
+ */
+ uint16_t req_buf_num_pages;
+ /* This field represents the number of pages used for request buffer(s). */
+ uint16_t req_buf_page_size;
+ /* This field represents the page size used for request buffer(s). */
+ /* 16 bytes */
+ #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_16B UINT32_C(0x4)
+ /* 4 Kbytes */
+ #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_4K UINT32_C(0xc)
+ /* 8 Kbytes */
+ #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_8K UINT32_C(0xd)
+ /* 64 Kbytes */
+ #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_64K UINT32_C(0x10)
+ /* 2 Mbytes */
+ #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_2M UINT32_C(0x15)
+ /* 4 Mbytes */
+ #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_4M UINT32_C(0x16)
+ /* 1 Gbytes */
+ #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_1G UINT32_C(0x1e)
+ uint16_t req_buf_len;
+ /* The length of the request buffer per VF in bytes. */
+ uint16_t resp_buf_len;
+ /* The length of the response buffer in bytes. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint64_t req_buf_page_addr0;
+ /* This field represents the page address of page #0. */
+ uint64_t req_buf_page_addr1;
+ /* This field represents the page address of page #1. */
+ uint64_t req_buf_page_addr2;
+ /* This field represents the page address of page #2. */
+ uint64_t req_buf_page_addr3;
+ /* This field represents the page address of page #3. */
+ uint64_t req_buf_page_addr4;
+ /* This field represents the page address of page #4. */
+ uint64_t req_buf_page_addr5;
+ /* This field represents the page address of page #5. */
+ uint64_t req_buf_page_addr6;
+ /* This field represents the page address of page #6. */
+ uint64_t req_buf_page_addr7;
+ /* This field represents the page address of page #7. */
+ uint64_t req_buf_page_addr8;
+ /* This field represents the page address of page #8. */
+ uint64_t req_buf_page_addr9;
+ /* This field represents the page address of page #9. */
+ uint64_t error_buf_addr;
+ /*
+ * This field is used to receive the error reporting from the chipset.
+ * Only applicable for PFs.
+ */
+ uint64_t resp_buf_addr;
+ /* This field is used to receive the response forwarded by the HWRM. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_buf_rgtr_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_buf_unrgtr */
+/*
+ * Description: This command is used by the PF driver to unregister buffers used
+ * in the PF-VF communication with the HWRM. The PF driver uses this command to
+ * unregister buffers for PF-VF communication. A parent PF may issue this
+ * command to unregister buffers for communication between the PF and a specific
+ * VF. If the VF ID is not valid, then this command is used to unregister
+ * buffers used for communications with all children VFs of the PF.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_buf_unrgtr_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the vf_id field to be configured. */
+ #define HWRM_FUNC_BUF_UNRGTR_INPUT_ENABLES_VF_ID UINT32_C(0x1)
+ uint16_t vf_id;
+ /*
+ * This value is used to identify a Virtual Function (VF). The scope of
+ * VF ID is local within a PF.
+ */
+ uint16_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_buf_unrgtr_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_func_drv_qver */
+/*
+ * Description: This command is used to query the version of the driver. Any
+ * driver version with major = 0, minor = 0, and update = 0 shall be considered
+ * an invalid or unknown version.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_func_drv_qver_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t reserved;
+ /* Reserved for future use */
+ uint16_t fid;
+ /*
+ * Function ID of the function that is being queried. 0xFF... (All Fs)
+ * if the query is for the requesting function.
+ */
+ uint16_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_func_drv_qver_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t os_type;
+ /* This value indicates the type of OS. */
+ /* Unknown */
+ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_UNKNOWN UINT32_C(0x0)
+ /* Other OS not listed below. */
+ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_OTHER UINT32_C(0x1)
+ /* MSDOS OS. */
+ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_MSDOS UINT32_C(0xe)
+ /* Windows OS. */
+ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_WINDOWS UINT32_C(0x12)
+ /* Solaris OS. */
+ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_SOLARIS UINT32_C(0x1d)
+ /* Linux OS. */
+ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_LINUX UINT32_C(0x24)
+ /* FreeBSD OS. */
+ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_FREEBSD UINT32_C(0x2a)
+ /* VMware ESXi OS. */
+ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_ESXI UINT32_C(0x68)
+ /* Microsoft Windows 8 64-bit OS. */
+ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_WIN864 UINT32_C(0x73)
+ /* Microsoft Windows Server 2012 R2 OS. */
+ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_WIN2012R2 UINT32_C(0x74)
+ uint8_t ver_maj;
+ /* This is the major version of the driver. */
+ uint8_t ver_min;
+ /* This is the minor version of the driver. */
+ uint8_t ver_upd;
+ /* This is the update version of the driver. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_phy_cfg */
+/*
+ * Description: This command configures the PHY device for the port. It allows
+ * setting of the most generic settings for the PHY. The HWRM shall complete
+ * this command as soon as PHY settings are configured. They may not be applied
+ * when the command response is provided. A VF driver shall not be allowed to
+ * configure PHY using this command. In a network partition mode, a PF driver
+ * shall not be allowed to configure PHY using this command.
+ */
+/* Input (56 bytes) */
+
+struct hwrm_port_phy_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * When this bit is set to '1', the PHY for the port shall be reset. #
+ * If this bit is set to 1, then the HWRM shall reset the PHY after
+ * applying PHY configuration changes specified in this command. # In
+ * order to guarantee that PHY configuration changes specified in this
+ * command take effect, the HWRM client should set this flag to 1. # If
+ * this bit is not set to 1, then the HWRM may reset the PHY depending
+ * on the current PHY configuration and settings specified in this
+ * command.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY UINT32_C(0x1)
+ /*
+ * When this bit is set to '1', the link shall be forced to be taken
+ * down. # When this bit is set to '1", all other command input settings
+ * related to the link speed shall be ignored. Once the link state is
+ * forced down, it can be explicitly cleared from that state by setting
+ * this flag to '0'. # If this flag is set to '0', then the link shall
+ * be cleared from forced down state if the link is in forced down
+ * state. There may be conditions (e.g. out-of-band or sideband
+ * configuration changes for the link) outside the scope of the HWRM
+ * implementation that may clear forced down link state.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE_LINK_DOWN UINT32_C(0x2)
+ /*
+ * When this bit is set to '1', the link shall be forced to the
+ * force_link_speed value. When this bit is set to '1', the HWRM client
+ * should not enable any of the auto negotiation related fields
+ * represented by auto_XXX fields in this command. When this bit is set
+ * to '1' and the HWRM client has enabled a auto_XXX field in this
+ * command, then the HWRM shall ignore the enabled auto_XXX field. When
+ * this bit is set to zero, the link shall be allowed to autoneg.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE UINT32_C(0x4)
+ /*
+ * When this bit is set to '1', the auto-negotiation process shall be
+ * restarted on the link.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG UINT32_C(0x8)
+ /*
+ * When this bit is set to '1', Energy Efficient Ethernet (EEE) is
+ * requested to be enabled on this link. If EEE is not supported on this
+ * port, then this flag shall be ignored by the HWRM.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE UINT32_C(0x10)
+ /*
+ * When this bit is set to '1', Energy Efficient Ethernet (EEE) is
+ * requested to be disabled on this link. If EEE is not supported on
+ * this port, then this flag shall be ignored by the HWRM.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE UINT32_C(0x20)
+ /*
+ * When this bit is set to '1' and EEE is enabled on this link, then TX
+ * LPI is requested to be enabled on the link. If EEE is not supported
+ * on this port, then this flag shall be ignored by the HWRM. If EEE is
+ * disabled on this port, then this flag shall be ignored by the HWRM.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI_ENABLE UINT32_C(0x40)
+ /*
+ * When this bit is set to '1' and EEE is enabled on this link, then TX
+ * LPI is requested to be disabled on the link. If EEE is not supported
+ * on this port, then this flag shall be ignored by the HWRM. If EEE is
+ * disabled on this port, then this flag shall be ignored by the HWRM.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI_DISABLE UINT32_C(0x80)
+ /*
+ * When set to 1, then the HWRM shall enable FEC autonegotitation on
+ * this port if supported. When set to 0, then this flag shall be
+ * ignored. If FEC autonegotiation is not supported, then the HWRM shall
+ * ignore this flag.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_AUTONEG_ENABLE UINT32_C(0x100)
+ /*
+ * When set to 1, then the HWRM shall disable FEC autonegotiation on
+ * this port if supported. When set to 0, then this flag shall be
+ * ignored. If FEC autonegotiation is not supported, then the HWRM shall
+ * ignore this flag.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_AUTONEG_DISABLE UINT32_C(0x200)
+ /*
+ * When set to 1, then the HWRM shall enable FEC CLAUSE 74 (Fire Code)
+ * on this port if supported. When set to 0, then this flag shall be
+ * ignored. If FEC CLAUSE 74 is not supported, then the HWRM shall
+ * ignore this flag.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_CLAUSE74_ENABLE UINT32_C(0x400)
+ /*
+ * When set to 1, then the HWRM shall disable FEC CLAUSE 74 (Fire Code)
+ * on this port if supported. When set to 0, then this flag shall be
+ * ignored. If FEC CLAUSE 74 is not supported, then the HWRM shall
+ * ignore this flag.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_CLAUSE74_DISABLE UINT32_C(0x800)
+ /*
+ * When set to 1, then the HWRM shall enable FEC CLAUSE 91 (Reed
+ * Solomon) on this port if supported. When set to 0, then this flag
+ * shall be ignored. If FEC CLAUSE 91 is not supported, then the HWRM
+ * shall ignore this flag.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_CLAUSE91_ENABLE UINT32_C(0x1000)
+ /*
+ * When set to 1, then the HWRM shall disable FEC CLAUSE 91 (Reed
+ * Solomon) on this port if supported. When set to 0, then this flag
+ * shall be ignored. If FEC CLAUSE 91 is not supported, then the HWRM
+ * shall ignore this flag.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_CLAUSE91_DISABLE UINT32_C(0x2000)
+ uint32_t enables;
+ /* This bit must be '1' for the auto_mode field to be configured. */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE UINT32_C(0x1)
+ /* This bit must be '1' for the auto_duplex field to be configured. */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_DUPLEX UINT32_C(0x2)
+ /* This bit must be '1' for the auto_pause field to be configured. */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE UINT32_C(0x4)
+ /* This bit must be '1' for the auto_link_speed field to be configured. */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED UINT32_C(0x8)
+ /*
+ * This bit must be '1' for the auto_link_speed_mask field to be
+ * configured.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED_MASK UINT32_C(0x10)
+ /* This bit must be '1' for the wirespeed field to be configured. */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_WIRESPEED UINT32_C(0x20)
+ /* This bit must be '1' for the lpbk field to be configured. */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_LPBK UINT32_C(0x40)
+ /* This bit must be '1' for the preemphasis field to be configured. */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_PREEMPHASIS UINT32_C(0x80)
+ /* This bit must be '1' for the force_pause field to be configured. */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE UINT32_C(0x100)
+ /*
+ * This bit must be '1' for the eee_link_speed_mask field to be
+ * configured.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_EEE_LINK_SPEED_MASK UINT32_C(0x200)
+ /* This bit must be '1' for the tx_lpi_timer field to be configured. */
+ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_TX_LPI_TIMER UINT32_C(0x400)
+ uint16_t port_id;
+ /* Port ID of port that is to be configured. */
+ uint16_t force_link_speed;
+ /*
+ * This is the speed that will be used if the force bit is '1'. If
+ * unsupported speed is selected, an error will be generated.
+ */
+ /* 100Mb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100MB UINT32_C(0x1)
+ /* 1Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_1GB UINT32_C(0xa)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_2GB UINT32_C(0x14)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_2_5GB UINT32_C(0x19)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10GB UINT32_C(0x64)
+ /* 20Mb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_20GB UINT32_C(0xc8)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_25GB UINT32_C(0xfa)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_40GB UINT32_C(0x190)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_50GB UINT32_C(0x1f4)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100GB UINT32_C(0x3e8)
+ /* 10Mb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10MB UINT32_C(0xffff)
+ uint8_t auto_mode;
+ /*
+ * This value is used to identify what autoneg mode is used when the
+ * link speed is not being forced.
+ */
+ /* Disable autoneg or autoneg disabled. No speeds are selected. */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_NONE UINT32_C(0x0)
+ /* Select all possible speeds for autoneg mode. */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS UINT32_C(0x1)
+ /*
+ * Select only the auto_link_speed speed for autoneg mode. This
+ * mode has been DEPRECATED. An HWRM client should not use this
+ * mode.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ONE_SPEED UINT32_C(0x2)
+ /*
+ * Select the auto_link_speed or any speed below that speed for
+ * autoneg. This mode has been DEPRECATED. An HWRM client should
+ * not use this mode.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ONE_OR_BELOW UINT32_C(0x3)
+ /*
+ * Select the speeds based on the corresponding link speed mask
+ * value that is provided.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK UINT32_C(0x4)
+ uint8_t auto_duplex;
+ /*
+ * This is the duplex setting that will be used if the autoneg_mode is
+ * "one_speed" or "one_or_below".
+ */
+ /* Half Duplex will be requested. */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_HALF UINT32_C(0x0)
+ /* Full duplex will be requested. */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_FULL UINT32_C(0x1)
+ /* Both Half and Full dupex will be requested. */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_BOTH UINT32_C(0x2)
+ uint8_t auto_pause;
+ /*
+ * This value is used to configure the pause that will be used for
+ * autonegotiation. Add text on the usage of auto_pause and force_pause.
+ */
+ /*
+ * When this bit is '1', Generation of tx pause messages has been
+ * requested. Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX UINT32_C(0x1)
+ /*
+ * When this bit is '1', Reception of rx pause messages has been
+ * requested. Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX UINT32_C(0x2)
+ /*
+ * When set to 1, the advertisement of pause is enabled. # When the
+ * auto_mode is not set to none and this flag is set to 1, then the
+ * auto_pause bits on this port are being advertised and autoneg pause
+ * results are being interpreted. # When the auto_mode is not set to
+ * none and this flag is set to 0, the pause is forced as indicated in
+ * force_pause, and also advertised as auto_pause bits, but the autoneg
+ * results are not interpreted since the pause configuration is being
+ * forced. # When the auto_mode is set to none and this flag is set to
+ * 1, auto_pause bits should be ignored and should be set to 0.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE UINT32_C(0x4)
+ uint8_t unused_0;
+ uint16_t auto_link_speed;
+ /*
+ * This is the speed that will be used if the autoneg_mode is
+ * "one_speed" or "one_or_below". If an unsupported speed is selected,
+ * an error will be generated.
+ */
+ /* 100Mb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_100MB UINT32_C(0x1)
+ /* 1Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_1GB UINT32_C(0xa)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_2GB UINT32_C(0x14)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_2_5GB UINT32_C(0x19)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_10GB UINT32_C(0x64)
+ /* 20Mb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_20GB UINT32_C(0xc8)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_25GB UINT32_C(0xfa)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_40GB UINT32_C(0x190)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_50GB UINT32_C(0x1f4)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_100GB UINT32_C(0x3e8)
+ /* 10Mb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_10MB UINT32_C(0xffff)
+ uint16_t auto_link_speed_mask;
+ /*
+ * This is a mask of link speeds that will be used if autoneg_mode is
+ * "mask". If unsupported speed is enabled an error will be generated.
+ */
+ /* 100Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_100MBHD UINT32_C(0x1)
+ /* 100Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_100MB UINT32_C(0x2)
+ /* 1Gb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_1GBHD UINT32_C(0x4)
+ /* 1Gb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_1GB UINT32_C(0x8)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_2GB UINT32_C(0x10)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_2_5GB UINT32_C(0x20)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10GB UINT32_C(0x40)
+ /* 20Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_20GB UINT32_C(0x80)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_25GB UINT32_C(0x100)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_40GB UINT32_C(0x200)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_50GB UINT32_C(0x400)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_100GB UINT32_C(0x800)
+ /* 10Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10MBHD UINT32_C(0x1000)
+ /* 10Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10MB UINT32_C(0x2000)
+ uint8_t wirespeed;
+ /* This value controls the wirespeed feature. */
+ /* Wirespeed feature is disabled. */
+ #define HWRM_PORT_PHY_CFG_INPUT_WIRESPEED_OFF UINT32_C(0x0)
+ /* Wirespeed feature is enabled. */
+ #define HWRM_PORT_PHY_CFG_INPUT_WIRESPEED_ON UINT32_C(0x1)
+ uint8_t lpbk;
+ /* This value controls the loopback setting for the PHY. */
+ /* No loopback is selected. Normal operation. */
+ #define HWRM_PORT_PHY_CFG_INPUT_LPBK_NONE UINT32_C(0x0)
+ /*
+ * The HW will be configured with local loopback such that host
+ * data is sent back to the host without modification.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_LPBK_LOCAL UINT32_C(0x1)
+ /*
+ * The HW will be configured with remote loopback such that port
+ * logic will send packets back out the transmitter that are
+ * received.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_LPBK_REMOTE UINT32_C(0x2)
+ uint8_t force_pause;
+ /*
+ * This value is used to configure the pause that will be used for force
+ * mode.
+ */
+ /*
+ * When this bit is '1', Generation of tx pause messages is supported.
+ * Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX UINT32_C(0x1)
+ /*
+ * When this bit is '1', Reception of rx pause messages is supported.
+ * Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX UINT32_C(0x2)
+ uint8_t unused_1;
+ uint32_t preemphasis;
+ /*
+ * This value controls the pre-emphasis to be used for the link. Driver
+ * should not set this value (use enable.preemphasis = 0) unless driver
+ * is sure of setting. Normally HWRM FW will determine proper pre-
+ * emphasis.
+ */
+ uint16_t eee_link_speed_mask;
+ /*
+ * Setting for link speed mask that is used to advertise speeds during
+ * autonegotiation when EEE is enabled. This field is valid only when
+ * EEE is enabled. The speeds specified in this field shall be a subset
+ * of speeds specified in auto_link_speed_mask. If EEE is enabled,then
+ * at least one speed shall be provided in this mask.
+ */
+ /* Reserved */
+ #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_RSVD1 UINT32_C(0x1)
+ /* 100Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_100MB UINT32_C(0x2)
+ /* Reserved */
+ #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_RSVD2 UINT32_C(0x4)
+ /* 1Gb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_1GB UINT32_C(0x8)
+ /* Reserved */
+ #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_RSVD3 UINT32_C(0x10)
+ /* Reserved */
+ #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_RSVD4 UINT32_C(0x20)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_10GB UINT32_C(0x40)
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint32_t tx_lpi_timer;
+ uint32_t unused_4;
+ /*
+ * Reuested setting of TX LPI timer in microseconds. This field is valid
+ * only when EEE is enabled and TX LPI is enabled.
+ */
+ #define HWRM_PORT_PHY_CFG_INPUT_TX_LPI_TIMER_MASK UINT32_C(0xffffff)
+ #define HWRM_PORT_PHY_CFG_INPUT_TX_LPI_TIMER_SFT 0
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_port_phy_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_phy_qcfg */
+/* Description: This command queries the PHY configuration for the port. */
+/* Input (24 bytes) */
+
+struct hwrm_port_phy_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t port_id;
+ /* Port ID of port that is to be queried. */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (96 bytes) */
+
+struct hwrm_port_phy_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t link;
+ /* This value indicates the current link status. */
+ /* There is no link or cable detected. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_NO_LINK UINT32_C(0x0)
+ /* There is no link, but a cable has been detected. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SIGNAL UINT32_C(0x1)
+ /* There is a link. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK UINT32_C(0x2)
+ uint8_t unused_0;
+ uint16_t link_speed;
+ /* This value indicates the current link speed of the connection. */
+ /* 100Mb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB UINT32_C(0x1)
+ /* 1Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB UINT32_C(0xa)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB UINT32_C(0x14)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB UINT32_C(0x19)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB UINT32_C(0x64)
+ /* 20Mb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB UINT32_C(0xc8)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB UINT32_C(0xfa)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB UINT32_C(0x190)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB UINT32_C(0x1f4)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB UINT32_C(0x3e8)
+ /* 10Mb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB UINT32_C(0xffff)
+ uint8_t duplex;
+ /* This value is indicates the duplex of the current connection. */
+ /* Half Duplex connection. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_HALF UINT32_C(0x0)
+ /* Full duplex connection. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL UINT32_C(0x1)
+ uint8_t pause;
+ /*
+ * This value is used to indicate the current pause configuration. When
+ * autoneg is enabled, this value represents the autoneg results of
+ * pause configuration.
+ */
+ /*
+ * When this bit is '1', Generation of tx pause messages is supported.
+ * Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX UINT32_C(0x1)
+ /*
+ * When this bit is '1', Reception of rx pause messages is supported.
+ * Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX UINT32_C(0x2)
+ uint16_t support_speeds;
+ /*
+ * The supported speeds for the port. This is a bit mask. For each speed
+ * that is supported, the corrresponding bit will be set to '1'.
+ */
+ /* 100Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MBHD UINT32_C(0x1)
+ /* 100Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MB UINT32_C(0x2)
+ /* 1Gb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GBHD UINT32_C(0x4)
+ /* 1Gb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB UINT32_C(0x8)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2GB UINT32_C(0x10)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB UINT32_C(0x20)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB UINT32_C(0x40)
+ /* 20Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB UINT32_C(0x80)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB UINT32_C(0x100)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB UINT32_C(0x200)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB UINT32_C(0x400)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB UINT32_C(0x800)
+ /* 10Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10MBHD UINT32_C(0x1000)
+ /* 10Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10MB UINT32_C(0x2000)
+ uint16_t force_link_speed;
+ /*
+ * Current setting of forced link speed. When the link speed is not
+ * being forced, this value shall be set to 0.
+ */
+ /* 100Mb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_100MB UINT32_C(0x1)
+ /* 1Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_1GB UINT32_C(0xa)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_2GB UINT32_C(0x14)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_2_5GB UINT32_C(0x19)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_10GB UINT32_C(0x64)
+ /* 20Mb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_20GB UINT32_C(0xc8)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_25GB UINT32_C(0xfa)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_40GB UINT32_C(0x190)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_50GB UINT32_C(0x1f4)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_100GB UINT32_C(0x3e8)
+ /* 10Mb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_10MB UINT32_C(0xffff)
+ uint8_t auto_mode;
+ /* Current setting of auto negotiation mode. */
+ /* Disable autoneg or autoneg disabled. No speeds are selected. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE UINT32_C(0x0)
+ /* Select all possible speeds for autoneg mode. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_ALL_SPEEDS UINT32_C(0x1)
+ /*
+ * Select only the auto_link_speed speed for autoneg mode. This
+ * mode has been DEPRECATED. An HWRM client should not use this
+ * mode.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_ONE_SPEED UINT32_C(0x2)
+ /*
+ * Select the auto_link_speed or any speed below that speed for
+ * autoneg. This mode has been DEPRECATED. An HWRM client should
+ * not use this mode.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_ONE_OR_BELOW UINT32_C(0x3)
+ /*
+ * Select the speeds based on the corresponding link speed mask
+ * value that is provided.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_SPEED_MASK UINT32_C(0x4)
+ uint8_t auto_pause;
+ /*
+ * Current setting of pause autonegotiation. Move autoneg_pause flag
+ * here.
+ */
+ /*
+ * When this bit is '1', Generation of tx pause messages has been
+ * requested. Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_PAUSE_TX UINT32_C(0x1)
+ /*
+ * When this bit is '1', Reception of rx pause messages has been
+ * requested. Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_PAUSE_RX UINT32_C(0x2)
+ /*
+ * When set to 1, the advertisement of pause is enabled. # When the
+ * auto_mode is not set to none and this flag is set to 1, then the
+ * auto_pause bits on this port are being advertised and autoneg pause
+ * results are being interpreted. # When the auto_mode is not set to
+ * none and this flag is set to 0, the pause is forced as indicated in
+ * force_pause, and also advertised as auto_pause bits, but the autoneg
+ * results are not interpreted since the pause configuration is being
+ * forced. # When the auto_mode is set to none and this flag is set to
+ * 1, auto_pause bits should be ignored and should be set to 0.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_PAUSE_AUTONEG_PAUSE UINT32_C(0x4)
+ uint16_t auto_link_speed;
+ /*
+ * Current setting for auto_link_speed. This field is only valid when
+ * auto_mode is set to "one_speed" or "one_or_below".
+ */
+ /* 100Mb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_100MB UINT32_C(0x1)
+ /* 1Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_1GB UINT32_C(0xa)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_2GB UINT32_C(0x14)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_2_5GB UINT32_C(0x19)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_10GB UINT32_C(0x64)
+ /* 20Mb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_20GB UINT32_C(0xc8)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_25GB UINT32_C(0xfa)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_40GB UINT32_C(0x190)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_50GB UINT32_C(0x1f4)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_100GB UINT32_C(0x3e8)
+ /* 10Mb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_10MB UINT32_C(0xffff)
+ uint16_t auto_link_speed_mask;
+ /*
+ * Current setting for auto_link_speed_mask that is used to advertise
+ * speeds during autonegotiation. This field is only valid when
+ * auto_mode is set to "mask". The speeds specified in this field shall
+ * be a subset of supported speeds on this port.
+ */
+ /* 100Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_100MBHD UINT32_C(0x1)
+ /* 100Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_100MB UINT32_C(0x2)
+ /* 1Gb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_1GBHD UINT32_C(0x4)
+ /* 1Gb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_1GB UINT32_C(0x8)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_2GB UINT32_C(0x10)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_2_5GB UINT32_C(0x20)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_10GB UINT32_C(0x40)
+ /* 20Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_20GB UINT32_C(0x80)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_25GB UINT32_C(0x100)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_40GB UINT32_C(0x200)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_50GB UINT32_C(0x400)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_100GB UINT32_C(0x800)
+ /* 10Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_10MBHD UINT32_C(0x1000)
+ /* 10Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_10MB UINT32_C(0x2000)
+ uint8_t wirespeed;
+ /* Current setting for wirespeed. */
+ /* Wirespeed feature is disabled. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_WIRESPEED_OFF UINT32_C(0x0)
+ /* Wirespeed feature is enabled. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_WIRESPEED_ON UINT32_C(0x1)
+ uint8_t lpbk;
+ /* Current setting for loopback. */
+ /* No loopback is selected. Normal operation. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LPBK_NONE UINT32_C(0x0)
+ /*
+ * The HW will be configured with local loopback such that host
+ * data is sent back to the host without modification.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LPBK_LOCAL UINT32_C(0x1)
+ /*
+ * The HW will be configured with remote loopback such that port
+ * logic will send packets back out the transmitter that are
+ * received.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LPBK_REMOTE UINT32_C(0x2)
+ uint8_t force_pause;
+ /*
+ * Current setting of forced pause. When the pause configuration is not
+ * being forced, then this value shall be set to 0.
+ */
+ /*
+ * When this bit is '1', Generation of tx pause messages is supported.
+ * Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_PAUSE_TX UINT32_C(0x1)
+ /*
+ * When this bit is '1', Reception of rx pause messages is supported.
+ * Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_PAUSE_RX UINT32_C(0x2)
+ uint8_t module_status;
+ /*
+ * This value indicates the current status of the optics module on this
+ * port.
+ */
+ /* Module is inserted and accepted */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_NONE UINT32_C(0x0)
+ /* Module is rejected and transmit side Laser is disabled. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_DISABLETX UINT32_C(0x1)
+ /* Module mismatch warning. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_WARNINGMSG UINT32_C(0x2)
+ /* Module is rejected and powered down. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_PWRDOWN UINT32_C(0x3)
+ /* Module is not inserted. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_NOTINSERTED UINT32_C(0x4)
+ /* Module status is not applicable. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_NOTAPPLICABLE UINT32_C(0xff)
+ uint32_t preemphasis;
+ /* Current setting for preemphasis. */
+ uint8_t phy_maj;
+ /* This field represents the major version of the PHY. */
+ uint8_t phy_min;
+ /* This field represents the minor version of the PHY. */
+ uint8_t phy_bld;
+ /* This field represents the build version of the PHY. */
+ uint8_t phy_type;
+ /* This value represents a PHY type. */
+ /* Unknown */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN UINT32_C(0x0)
+ /* BASE-CR */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR UINT32_C(0x1)
+ /* BASE-KR4 (Deprecated) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4 UINT32_C(0x2)
+ /* BASE-LR */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR UINT32_C(0x3)
+ /* BASE-SR */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR UINT32_C(0x4)
+ /* BASE-KR2 (Deprecated) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2 UINT32_C(0x5)
+ /* BASE-KX */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX UINT32_C(0x6)
+ /* BASE-KR */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR UINT32_C(0x7)
+ /* BASE-T */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET UINT32_C(0x8)
+ /* EEE capable BASE-T */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE UINT32_C(0x9)
+ /* SGMII connected external PHY */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY UINT32_C(0xa)
+ uint8_t media_type;
+ /* This value represents a media type. */
+ /* Unknown */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_UNKNOWN UINT32_C(0x0)
+ /* Twisted Pair */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_TP UINT32_C(0x1)
+ /* Direct Attached Copper */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_DAC UINT32_C(0x2)
+ /* Fiber */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_FIBRE UINT32_C(0x3)
+ uint8_t xcvr_pkg_type;
+ /* This value represents a transceiver type. */
+ /* PHY and MAC are in the same package */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_PKG_TYPE_XCVR_INTERNAL UINT32_C(0x1)
+ /* PHY and MAC are in different packages */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_PKG_TYPE_XCVR_EXTERNAL UINT32_C(0x2)
+ uint8_t eee_config_phy_addr;
+ /*
+ * This field represents flags related to EEE configuration. These EEE
+ * configuration flags are valid only when the auto_mode is not set to
+ * none (in other words autonegotiation is enabled).
+ */
+ /* This field represents PHY address. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK UINT32_C(0x1f)
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_SFT 0
+ /*
+ * When set to 1, Energy Efficient Ethernet (EEE) mode is enabled.
+ * Speeds for autoneg with EEE mode enabled are based on
+ * eee_link_speed_mask.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_EEE_ENABLED UINT32_C(0x20)
+ /*
+ * This flag is valid only when eee_enabled is set to 1. # If
+ * eee_enabled is set to 0, then EEE mode is disabled and this flag
+ * shall be ignored. # If eee_enabled is set to 1 and this flag is set
+ * to 1, then Energy Efficient Ethernet (EEE) mode is enabled and in
+ * use. # If eee_enabled is set to 1 and this flag is set to 0, then
+ * Energy Efficient Ethernet (EEE) mode is enabled but is currently not
+ * in use.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_EEE_ACTIVE UINT32_C(0x40)
+ /*
+ * This flag is valid only when eee_enabled is set to 1. # If
+ * eee_enabled is set to 0, then EEE mode is disabled and this flag
+ * shall be ignored. # If eee_enabled is set to 1 and this flag is set
+ * to 1, then Energy Efficient Ethernet (EEE) mode is enabled and TX LPI
+ * is enabled. # If eee_enabled is set to 1 and this flag is set to 0,
+ * then Energy Efficient Ethernet (EEE) mode is enabled but TX LPI is
+ * disabled.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_EEE_TX_LPI UINT32_C(0x80)
+ /*
+ * This field represents flags related to EEE configuration. These EEE
+ * configuration flags are valid only when the auto_mode is not set to
+ * none (in other words autonegotiation is enabled).
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_MASK UINT32_C(0xe0)
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_SFT 5
+ uint8_t parallel_detect;
+ /* Reserved field, set to 0 */
+ /*
+ * When set to 1, the parallel detection is used to determine the speed
+ * of the link partner. Parallel detection is used when a
+ * autonegotiation capable device is connected to a link parter that is
+ * not capable of autonegotiation.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_PARALLEL_DETECT UINT32_C(0x1)
+ /* Reserved field, set to 0 */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_RESERVED_MASK UINT32_C(0xfe)
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_RESERVED_SFT 1
+ uint16_t link_partner_adv_speeds;
+ /*
+ * The advertised speeds for the port by the link partner. Each
+ * advertised speed will be set to '1'.
+ */
+ /* 100Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_100MBHD UINT32_C(0x1)
+ /* 100Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_100MB UINT32_C(0x2)
+ /* 1Gb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_1GBHD UINT32_C(0x4)
+ /* 1Gb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_1GB UINT32_C(0x8)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_2GB UINT32_C(0x10)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_2_5GB UINT32_C(0x20)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_10GB UINT32_C(0x40)
+ /* 20Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_20GB UINT32_C(0x80)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_25GB UINT32_C(0x100)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_40GB UINT32_C(0x200)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_50GB UINT32_C(0x400)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_100GB UINT32_C(0x800)
+ /* 10Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_10MBHD UINT32_C(0x1000)
+ /* 10Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_10MB UINT32_C(0x2000)
+ uint8_t link_partner_adv_auto_mode;
+ /*
+ * The advertised autoneg for the port by the link partner. This field
+ * is deprecated and should be set to 0.
+ */
+ /* Disable autoneg or autoneg disabled. No speeds are selected. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_NONE UINT32_C(0x0)
+ /* Select all possible speeds for autoneg mode. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_ALL_SPEEDS UINT32_C(0x1)
+ /*
+ * Select only the auto_link_speed speed for autoneg mode. This
+ * mode has been DEPRECATED. An HWRM client should not use this
+ * mode.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_ONE_SPEED UINT32_C(0x2)
+ /*
+ * Select the auto_link_speed or any speed below that speed for
+ * autoneg. This mode has been DEPRECATED. An HWRM client should
+ * not use this mode.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_ONE_OR_BELOW UINT32_C(0x3)
+ /*
+ * Select the speeds based on the corresponding link speed mask
+ * value that is provided.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_SPEED_MASK UINT32_C(0x4)
+ uint8_t link_partner_adv_pause;
+ /* The advertised pause settings on the port by the link partner. */
+ /*
+ * When this bit is '1', Generation of tx pause messages is supported.
+ * Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_PAUSE_TX UINT32_C(0x1)
+ /*
+ * When this bit is '1', Reception of rx pause messages is supported.
+ * Disabled otherwise.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_PAUSE_RX UINT32_C(0x2)
+ uint16_t adv_eee_link_speed_mask;
+ /*
+ * Current setting for link speed mask that is used to advertise speeds
+ * during autonegotiation when EEE is enabled. This field is valid only
+ * when eee_enabled flags is set to 1. The speeds specified in this
+ * field shall be a subset of speeds specified in auto_link_speed_mask.
+ */
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_RSVD1 UINT32_C(0x1)
+ /* 100Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_100MB UINT32_C(0x2)
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_RSVD2 UINT32_C(0x4)
+ /* 1Gb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_1GB UINT32_C(0x8)
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_RSVD3 UINT32_C(0x10)
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_RSVD4 UINT32_C(0x20)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_10GB UINT32_C(0x40)
+ uint16_t link_partner_adv_eee_link_speed_mask;
+ /*
+ * Current setting for link speed mask that is advertised by the link
+ * partner when EEE is enabled. This field is valid only when
+ * eee_enabled flags is set to 1.
+ */
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD1 UINT32_C(0x1)
+ /* 100Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_100MB UINT32_C(0x2)
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD2 UINT32_C(0x4)
+ /* 1Gb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_1GB UINT32_C(0x8)
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD3 UINT32_C(0x10)
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD4 UINT32_C(0x20)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_10GB UINT32_C(0x40)
+ uint32_t xcvr_identifier_type_tx_lpi_timer;
+ /* This value represents transceiver identifier type. */
+ /*
+ * Current setting of TX LPI timer in microseconds. This field is valid
+ * only when_eee_enabled flag is set to 1 and tx_lpi_enabled is set to
+ * 1.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_TX_LPI_TIMER_MASK UINT32_C(0xffffff)
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_TX_LPI_TIMER_SFT 0
+ /* This value represents transceiver identifier type. */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_MASK UINT32_C(0xff000000)
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_SFT 24
+ /* Unknown */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_UNKNOWN (UINT32_C(0x0) << 24)
+ /* SFP/SFP+/SFP28 */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_SFP (UINT32_C(0x3) << 24)
+ /* QSFP */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP (UINT32_C(0xc) << 24)
+ /* QSFP+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFPPLUS (UINT32_C(0xd) << 24)
+ /* QSFP28 */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP28 (UINT32_C(0x11) << 24)
+ uint16_t fec_cfg;
+ /*
+ * This value represents the current configuration of Forward Error
+ * Correction (FEC) on the port.
+ */
+ /*
+ * When set to 1, then FEC is not supported on this port. If this flag
+ * is set to 1, then all other FEC configuration flags shall be ignored.
+ * When set to 0, then FEC is supported as indicated by other
+ * configuration flags. If no cable is attached and the HWRM does not
+ * yet know the FEC capability, then the HWRM shall set this flag to 1
+ * when reporting FEC capability.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_NONE_SUPPORTED UINT32_C(0x1)
+ /*
+ * When set to 1, then FEC autonegotiation is supported on this port.
+ * When set to 0, then FEC autonegotiation is not supported on this
+ * port.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_AUTONEG_SUPPORTED UINT32_C(0x2)
+ /*
+ * When set to 1, then FEC autonegotiation is enabled on this port. When
+ * set to 0, then FEC autonegotiation is disabled if supported. This
+ * flag should be ignored if FEC autonegotiation is not supported on
+ * this port.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_AUTONEG_ENABLED UINT32_C(0x4)
+ /*
+ * When set to 1, then FEC CLAUSE 74 (Fire Code) is supported on this
+ * port. When set to 0, then FEC CLAUSE 74 (Fire Code) is not supported
+ * on this port.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE74_SUPPORTED UINT32_C(0x8)
+ /*
+ * When set to 1, then FEC CLAUSE 74 (Fire Code) is enabled on this
+ * port. When set to 0, then FEC CLAUSE 74 (Fire Code) is disabled if
+ * supported. This flag should be ignored if FEC CLAUSE 74 is not
+ * supported on this port.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE74_ENABLED UINT32_C(0x10)
+ /*
+ * When set to 1, then FEC CLAUSE 91 (Reed Solomon) is supported on this
+ * port. When set to 0, then FEC CLAUSE 91 (Reed Solomon) is not
+ * supported on this port.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE91_SUPPORTED UINT32_C(0x20)
+ /*
+ * When set to 1, then FEC CLAUSE 91 (Reed Solomon) is enabled on this
+ * port. When set to 0, then FEC CLAUSE 91 (Reed Solomon) is disabled if
+ * supported. This flag should be ignored if FEC CLAUSE 91 is not
+ * supported on this port.
+ */
+ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE91_ENABLED UINT32_C(0x40)
+ uint8_t unused_1;
+ uint8_t unused_2;
+ char phy_vendor_name[16];
+ /*
+ * Up to 16 bytes of null padded ASCII string representing PHY vendor.
+ * If the string is set to null, then the vendor name is not available.
+ */
+ char phy_vendor_partnumber[16];
+ /*
+ * Up to 16 bytes of null padded ASCII string that identifies vendor
+ * specific part number of the PHY. If the string is set to null, then
+ * the vendor specific part number is not available.
+ */
+ uint32_t unused_3;
+ uint8_t unused_4;
+ uint8_t unused_5;
+ uint8_t unused_6;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_mac_cfg */
+/* Description: This command configures the MAC block for the port. */
+/* Input (40 bytes) */
+
+struct hwrm_port_mac_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * When this bit is '1', this command will configure the MAC to match
+ * the current link state of the PHY. If the link is not established on
+ * the PHY, then this bit has no effect.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_MATCH_LINK UINT32_C(0x1)
+ /*
+ * When this bit is '1', the CoS assignment logic is enabled. When this
+ * logic is enabled, then inner VLAN PRI to CoS mapping is enabled. If
+ * this bit is '0', then the default CoS is used.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_COS_ASSIGNMENT_ENABLE UINT32_C(0x2)
+ /*
+ * When this bit is '1', tunnel or outer VLAN PRI field to CoS mapping
+ * is enabled. If this bit is '0', then outer VLAN PRI bits are not used
+ * in determining CoS.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_TUNNEL_PRI2COS_ENABLE UINT32_C(0x4)
+ /*
+ * When this bit is '1', the IP DSCP to CoS mapping is enabled. If this
+ * bit is '0', then IP DSCP bits are not used in determining CoS.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_IP_DSCP2COS_ENABLE UINT32_C(0x8)
+ /*
+ * When this bit is '1', the HWRM is requested to enable timestamp
+ * capture capability on the receive side of this port.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_PTP_RX_TS_CAPTURE_ENABLE UINT32_C(0x10)
+ /*
+ * When this bit is '1', the HWRM is requested to disable timestamp
+ * capture capability on the receive side of this port.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_PTP_RX_TS_CAPTURE_DISABLE UINT32_C(0x20)
+ /*
+ * When this bit is '1', the HWRM is requested to enable timestamp
+ * capture capability on the transmit side of this port.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_PTP_TX_TS_CAPTURE_ENABLE UINT32_C(0x40)
+ /*
+ * When this bit is '1', the HWRM is requested to disable timestamp
+ * capture capability on the transmit side of this port.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_PTP_TX_TS_CAPTURE_DISABLE UINT32_C(0x80)
+ /*
+ * When this bit is '1', the Out-Of-Box WoL is requested to be enabled
+ * on this port.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_OOB_WOL_ENABLE UINT32_C(0x100)
+ /*
+ * When this bit is '1', the the Out-Of-Box WoL is requested to be
+ * disabled on this port.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_OOB_WOL_DISABLE UINT32_C(0x200)
+ uint32_t enables;
+ /* This bit must be '1' for the ipg field to be configured. */
+ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_IPG UINT32_C(0x1)
+ /* This bit must be '1' for the lpbk field to be configured. */
+ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_LPBK UINT32_C(0x2)
+ /*
+ * This bit must be '1' for the ivlan_pri2cos_map_pri field to be
+ * configured.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_IVLAN_PRI2COS_MAP_PRI UINT32_C(0x4)
+ /* This bit must be '1' for the lcos_map_pri field to be configured. */
+ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_LCOS_MAP_PRI UINT32_C(0x8)
+ /*
+ * This bit must be '1' for the tunnel_pri2cos_map_pri field to be
+ * configured.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_TUNNEL_PRI2COS_MAP_PRI UINT32_C(0x10)
+ /* This bit must be '1' for the dscp2cos_map_pri field to be configured. */
+ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_DSCP2COS_MAP_PRI UINT32_C(0x20)
+ /*
+ * This bit must be '1' for the rx_ts_capture_ptp_msg_type field to be
+ * configured.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE UINT32_C(0x40)
+ /*
+ * This bit must be '1' for the tx_ts_capture_ptp_msg_type field to be
+ * configured.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_TX_TS_CAPTURE_PTP_MSG_TYPE UINT32_C(0x80)
+ uint16_t port_id;
+ /* Port ID of port that is to be configured. */
+ uint8_t ipg;
+ /*
+ * This value is used to configure the minimum IPG that will be sent
+ * between packets by this port.
+ */
+ uint8_t lpbk;
+ /* This value controls the loopback setting for the MAC. */
+ /* No loopback is selected. Normal operation. */
+ #define HWRM_PORT_MAC_CFG_INPUT_LPBK_NONE UINT32_C(0x0)
+ /*
+ * The HW will be configured with local loopback such that host
+ * data is sent back to the host without modification.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_LPBK_LOCAL UINT32_C(0x1)
+ /*
+ * The HW will be configured with remote loopback such that port
+ * logic will send packets back out the transmitter that are
+ * received.
+ */
+ #define HWRM_PORT_MAC_CFG_INPUT_LPBK_REMOTE UINT32_C(0x2)
+ uint8_t ivlan_pri2cos_map_pri;
+ /*
+ * This value controls the priority of mapping. Valid values: 1-4 Higher
+ * the number, higher the priority
+ */
+ uint8_t lcos_map_pri;
+ /*
+ * This value controls the priority of mapping. Valid values: 1-4 Higher
+ * the number, higher the priority
+ */
+ uint8_t tunnel_pri2cos_map_pri;
+ /*
+ * This value controls the priority of mapping. Valid values: 1-4 Higher
+ * the number, higher the priority
+ */
+ uint8_t dscp2pri_map_pri;
+ /*
+ * This value controls the priority of mapping. Valid values: 1-4 Higher
+ * the number, higher the priority
+ */
+ uint16_t rx_ts_capture_ptp_msg_type;
+ /*
+ * This is a 16-bit bit mask that is used to request a specific
+ * configuration of time stamp capture of PTP messages on the receive
+ * side of this port. This field shall be ignored if the
+ * ptp_rx_ts_capture_enable flag is not set in this command. Otherwise,
+ * if bit 'i' is set, then the HWRM is being requested to configure the
+ * receive side of the port to capture the time stamp of every received
+ * PTP message with messageType field value set to i.
+ */
+ uint16_t tx_ts_capture_ptp_msg_type;
+ /*
+ * This is a 16-bit bit mask that is used to request a specific
+ * configuration of time stamp capture of PTP messages on the transmit
+ * side of this port. This field shall be ignored if the
+ * ptp_tx_ts_capture_enable flag is not set in this command. Otherwise,
+ * if bit 'i' is set, then the HWRM is being requested to configure the
+ * transmit sied of the port to capture the time stamp of every
+ * transmitted PTP message with messageType field value set to i.
+ */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_port_mac_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t mru;
+ /*
+ * This is the configured maximum length of Ethernet packet payload that
+ * is allowed to be received on the port. This value does not include
+ * the number of bytes used by Ethernet header and trailer (CRC).
+ */
+ uint16_t mtu;
+ /*
+ * This is the configured maximum length of Ethernet packet payload that
+ * is allowed to be transmitted on the port. This value does not include
+ * the number of bytes used by Ethernet header and trailer (CRC).
+ */
+ uint8_t ipg;
+ /* Current configuration of the IPG value. */
+ uint8_t lpbk;
+ /* Current value of the loopback value. */
+ /* No loopback is selected. Normal operation. */
+ #define HWRM_PORT_MAC_CFG_OUTPUT_LPBK_NONE UINT32_C(0x0)
+ /*
+ * The HW will be configured with local loopback such that host
+ * data is sent back to the host without modification.
+ */
+ #define HWRM_PORT_MAC_CFG_OUTPUT_LPBK_LOCAL UINT32_C(0x1)
+ /*
+ * The HW will be configured with remote loopback such that port
+ * logic will send packets back out the transmitter that are
+ * received.
+ */
+ #define HWRM_PORT_MAC_CFG_OUTPUT_LPBK_REMOTE UINT32_C(0x2)
+ uint8_t unused_0;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_mac_qcfg */
+/* Description: This command queries the MAC block for the port. */
+/* Input (24 bytes) */
+
+struct hwrm_port_mac_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t port_id;
+ /* Port ID of port that is to be configured. */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_port_mac_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t mru;
+ /*
+ * This is the configured maximum length of Ethernet packet payload that
+ * is allowed to be received on the port. This value does not include
+ * the number of bytes used by the Ethernet header and trailer (CRC).
+ */
+ uint16_t mtu;
+ /*
+ * This is the configured maximum length of Ethernet packet payload that
+ * is allowed to be transmitted on the port. This value does not include
+ * the number of bytes used by the Ethernet header and trailer (CRC).
+ */
+ uint8_t ipg;
+ /* The minimum IPG that will be sent between packets by this port. */
+ uint8_t lpbk;
+ /* The loopback setting for the MAC. */
+ /* No loopback is selected. Normal operation. */
+ #define HWRM_PORT_MAC_QCFG_OUTPUT_LPBK_NONE UINT32_C(0x0)
+ /*
+ * The HW will be configured with local loopback such that host
+ * data is sent back to the host without modification.
+ */
+ #define HWRM_PORT_MAC_QCFG_OUTPUT_LPBK_LOCAL UINT32_C(0x1)
+ /*
+ * The HW will be configured with remote loopback such that port
+ * logic will send packets back out the transmitter that are
+ * received.
+ */
+ #define HWRM_PORT_MAC_QCFG_OUTPUT_LPBK_REMOTE UINT32_C(0x2)
+ uint8_t ivlan_pri2cos_map_pri;
+ /*
+ * Priority of pri to CoS mapping. Valid values: 1-4 Higher the number,
+ * higher the priority Value 0 indicates that this mapping is not used.
+ */
+ uint8_t lcos_map_pri;
+ /*
+ * Priority of local CoS to PRI mapping. Valid values: 1-4 Higher the
+ * number, higher the priority Value 0 indicates that this mapping is
+ * not used.
+ */
+ uint8_t tunnel_pri2cos_map_pri;
+ /*
+ * Priority of tunnel PRI to CoS mapping. Valid values: 1-4 Higher the
+ * number, higher the priority Value 0 indicates that this mapping is
+ * not used.
+ */
+ uint8_t dscp2pri_map_pri;
+ /*
+ * Priority of DSCP to PRI mapping. Valid values: 1-4 Higher the number,
+ * higher the priority Value 0 indicates that this mapping is not used.
+ */
+ uint16_t rx_ts_capture_ptp_msg_type;
+ /*
+ * This is a 16-bit bit mask that represents the current configuration
+ * of time stamp capture of PTP messages on the receive side of this
+ * port. If bit 'i' is set, then the receive side of the port is
+ * configured to capture the time stamp of every received PTP message
+ * with messageType field value set to i. If all bits are set to 0 (i.e.
+ * field value set 0), then the receive side of the port is not
+ * configured to capture timestamp for PTP messages. If all bits are set
+ * to 1, then the receive side of the port is configured to capture
+ * timestamp for all PTP messages.
+ */
+ uint16_t tx_ts_capture_ptp_msg_type;
+ /*
+ * This is a 16-bit bit mask that represents the current configuration
+ * of time stamp capture of PTP messages on the transmit side of this
+ * port. If bit 'i' is set, then the transmit side of the port is
+ * configured to capture the time stamp of every received PTP message
+ * with messageType field value set to i. If all bits are set to 0 (i.e.
+ * field value set 0), then the transmit side of the port is not
+ * configured to capture timestamp for PTP messages. If all bits are set
+ * to 1, then the transmit side of the port is configured to capture
+ * timestamp for all PTP messages.
+ */
+ uint8_t unused_0;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_qstats */
+/* Description: This function returns per port Ethernet statistics. */
+/* Input (40 bytes) */
+
+struct hwrm_port_qstats_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t port_id;
+ /* Port ID of port that is being queried. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2[3];
+ uint8_t unused_3;
+ uint64_t tx_stat_host_addr;
+ /* This is the host address where Tx port statistics will be stored */
+ uint64_t rx_stat_host_addr;
+ /* This is the host address where Rx port statistics will be stored */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_port_qstats_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t tx_stat_size;
+ /* The size of TX port statistics block in bytes. */
+ uint16_t rx_stat_size;
+ /* The size of RX port statistics block in bytes. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_lpbk_qstats */
+/* Description: This function returns loopback statistics. */
+/* Input (16 bytes) */
+
+struct hwrm_port_lpbk_qstats_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+} __attribute__((packed));
+
+/* Output (96 bytes) */
+
+struct hwrm_port_lpbk_qstats_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint64_t lpbk_ucast_frames;
+ /* Number of transmitted unicast frames */
+ uint64_t lpbk_mcast_frames;
+ /* Number of transmitted multicast frames */
+ uint64_t lpbk_bcast_frames;
+ /* Number of transmitted broadcast frames */
+ uint64_t lpbk_ucast_bytes;
+ /* Number of transmitted bytes for unicast traffic */
+ uint64_t lpbk_mcast_bytes;
+ /* Number of transmitted bytes for multicast traffic */
+ uint64_t lpbk_bcast_bytes;
+ /* Number of transmitted bytes for broadcast traffic */
+ uint64_t tx_stat_discard;
+ /* Total Tx Drops for loopback traffic reported by STATS block */
+ uint64_t tx_stat_error;
+ /* Total Tx Error Drops for loopback traffic reported by STATS block */
+ uint64_t rx_stat_discard;
+ /* Total Rx Drops for loopback traffic reported by STATS block */
+ uint64_t rx_stat_error;
+ /* Total Rx Error Drops for loopback traffic reported by STATS block */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_clr_stats */
+/*
+ * Description: This function clears per port statistics. The HWRM shall not
+ * allow a VF driver to clear port statistics. The HWRM shall not allow a PF
+ * driver to clear port statistics in a partitioning mode. The HWRM may allow a
+ * PF driver to clear port statistics in the non-partitioning mode.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_port_clr_stats_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t port_id;
+ /* Port ID of port that is being queried. */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_port_clr_stats_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_lpbk_clr_stats */
+/*
+ * Description: This function clears loopback statistics. The HWRM shall not
+ * allow a VF driver to clear loopback statistics. The HWRM shall not allow a PF
+ * driver to clear loopback statistics in a partitioning mode. The HWRM may
+ * allow a PF driver to clear loopback statistics in the non-partitioning mode.
+ */
+/* Input (16 bytes) */
+
+struct hwrm_port_lpbk_clr_stats_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_port_lpbk_clr_stats_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_blink_led */
+/*
+ * Description: This function blinks the port LED for the specified number of
+ * times.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_port_blink_led_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t num_blinks;
+ /* Number of blinks. */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_port_blink_led_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_ts_query */
+/*
+ * Description: This function is used to read timestamp information captured for
+ * PTP messages on this port.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_port_ts_query_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_TX UINT32_C(0x0)
+ /* rx path */
+ #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_RX UINT32_C(0x1)
+ #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_LAST HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_RX
+ uint16_t port_id;
+ /* Port ID of port that is being queried. */
+ uint16_t unused_0;
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_port_ts_query_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint64_t ptp_msg_ts;
+ /* Timestamp value of PTP message captured. */
+ uint16_t ptp_msg_seqid;
+ /* Sequence ID of the PTP message captured. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_port_phy_qcaps */
+/*
+ * Description: This function is used to query the current capabilities of PHY
+ * on this link.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_port_phy_qcaps_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t port_id;
+ /* Port ID of port that is being queried. */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_port_phy_qcaps_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t eee_supported;
+ /*
+ * Reserved field. The HWRM shall set this field to 0. An HWRM client
+ * shall ignore this field.
+ */
+ /*
+ * If set to 1, then this field indicates that the link is capable of
+ * supporting EEE.
+ */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_EEE_SUPPORTED UINT32_C(0x1)
+ /*
+ * Reserved field. The HWRM shall set this field to 0. An HWRM client
+ * shall ignore this field.
+ */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_RSVD1_MASK UINT32_C(0xfe)
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_RSVD1_SFT 1
+ uint8_t unused_0;
+ uint16_t supported_speeds_force_mode;
+ /*
+ * This is a bit mask to indicate what speeds are supported as forced
+ * speeds on this link. For each speed that can be forced on this link,
+ * the corresponding mask bit shall be set to '1'.
+ */
+ /* 100Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_100MBHD UINT32_C(0x1)
+ /* 100Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_100MB UINT32_C(0x2)
+ /* 1Gb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_1GBHD UINT32_C(0x4)
+ /* 1Gb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_1GB UINT32_C(0x8)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_2GB UINT32_C(0x10)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_2_5GB UINT32_C(0x20)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_10GB UINT32_C(0x40)
+ /* 20Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_20GB UINT32_C(0x80)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_25GB UINT32_C(0x100)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_40GB UINT32_C(0x200)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_50GB UINT32_C(0x400)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_100GB UINT32_C(0x800)
+ /* 10Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_10MBHD UINT32_C(0x1000)
+ /* 10Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_10MB UINT32_C(0x2000)
+ uint16_t supported_speeds_auto_mode;
+ /*
+ * This is a bit mask to indicate what speeds are supported for
+ * autonegotiation on this link. For each speed that can be
+ * autonegotiated on this link, the corresponding mask bit shall be set
+ * to '1'.
+ */
+ /* 100Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_100MBHD UINT32_C(0x1)
+ /* 100Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_100MB UINT32_C(0x2)
+ /* 1Gb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_1GBHD UINT32_C(0x4)
+ /* 1Gb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_1GB UINT32_C(0x8)
+ /* 2Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_2GB UINT32_C(0x10)
+ /* 2.5Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_2_5GB UINT32_C(0x20)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_10GB UINT32_C(0x40)
+ /* 20Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_20GB UINT32_C(0x80)
+ /* 25Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_25GB UINT32_C(0x100)
+ /* 40Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_40GB UINT32_C(0x200)
+ /* 50Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_50GB UINT32_C(0x400)
+ /* 100Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_100GB UINT32_C(0x800)
+ /* 10Mb link speed (Half-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_10MBHD UINT32_C(0x1000)
+ /* 10Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_10MB UINT32_C(0x2000)
+ uint16_t supported_speeds_eee_mode;
+ /*
+ * This is a bit mask to indicate what speeds are supported for EEE on
+ * this link. For each speed that can be autonegotiated when EEE is
+ * enabled on this link, the corresponding mask bit shall be set to '1'.
+ * This field is only valid when the eee_suppotred is set to '1'.
+ */
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_RSVD1 UINT32_C(0x1)
+ /* 100Mb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_100MB UINT32_C(0x2)
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_RSVD2 UINT32_C(0x4)
+ /* 1Gb link speed (Full-duplex) */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_1GB UINT32_C(0x8)
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_RSVD3 UINT32_C(0x10)
+ /* Reserved */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_RSVD4 UINT32_C(0x20)
+ /* 10Gb link speed */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_10GB UINT32_C(0x40)
+ uint32_t tx_lpi_timer_low;
+ /*
+ * Reserved field. The HWRM shall set this field to 0. An HWRM client
+ * shall ignore this field.
+ */
+ /*
+ * The lowest value of TX LPI timer that can be set on this link when
+ * EEE is enabled. This value is in microseconds. This field is valid
+ * only when_eee_supported is set to '1'.
+ */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_LOW_MASK UINT32_C(0xffffff)
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_LOW_SFT 0
+ /*
+ * Reserved field. The HWRM shall set this field to 0. An HWRM client
+ * shall ignore this field.
+ */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_RSVD2_MASK UINT32_C(0xff000000)
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_RSVD2_SFT 24
+ uint32_t valid_tx_lpi_timer_high;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+ /*
+ * The highest value of TX LPI timer that can be set on this link when
+ * EEE is enabled. This value is in microseconds. This field is valid
+ * only when_eee_supported is set to '1'.
+ */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_HIGH_MASK UINT32_C(0xffffff)
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_HIGH_SFT 0
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_VALID_MASK UINT32_C(0xff000000)
+ #define HWRM_PORT_PHY_QCAPS_OUTPUT_VALID_SFT 24
+} __attribute__((packed));
+
+/* hwrm_queue_qportcfg */
+/*
+ * Description: This function is called by a driver to query queue configuration
+ * of a port. # The HWRM shall at least advertise one queue with lossy service
+ * profile. # The driver shall use this command to query queue ids before
+ * configuring or using any queues. # If a service profile is not set for a
+ * queue, then the driver shall not use that queue without configuring a service
+ * profile for it. # If the driver is not allowed to configure service profiles,
+ * then the driver shall only use queues for which service profiles are pre-
+ * configured.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_queue_qportcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0)
+ /* rx path */
+ #define HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1)
+ #define HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_RX
+ uint16_t port_id;
+ /*
+ * Port ID of port for which the queue configuration is being queried.
+ * This field is only required when sent by IPC.
+ */
+ uint16_t unused_0;
+} __attribute__((packed));
+
+/* Output (32 bytes) */
+
+struct hwrm_queue_qportcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t max_configurable_queues;
+ /* The maximum number of queues that can be configured. */
+ uint8_t max_configurable_lossless_queues;
+ /* The maximum number of lossless queues that can be configured. */
+ uint8_t queue_cfg_allowed;
+ /*
+ * 0 - Not allowed. Non-zero - Allowed. If this value is non-zero, then
+ * the HWRM shall allow the host SW driver to configure queues using
+ * hwrm_queue_cfg.
+ */
+ uint8_t queue_buffers_cfg_allowed;
+ /*
+ * 0 - Not allowed. Non-zero - Allowed If this value is non-zero, then
+ * the HWRM shall allow the host SW driver to configure queue buffers
+ * using hwrm_queue_buffers_cfg.
+ */
+ uint8_t queue_pfcenable_cfg_allowed;
+ /*
+ * 0 - Not allowed. Non-zero - Allowed If this value is non-zero, then
+ * the HWRM shall allow the host SW driver to configure PFC using
+ * hwrm_queue_pfcenable_cfg.
+ */
+ uint8_t queue_pri2cos_cfg_allowed;
+ /*
+ * 0 - Not allowed. Non-zero - Allowed If this value is non-zero, then
+ * the HWRM shall allow the host SW driver to configure Priority to CoS
+ * mapping using hwrm_queue_pri2cos_cfg.
+ */
+ uint8_t queue_cos2bw_cfg_allowed;
+ /*
+ * 0 - Not allowed. Non-zero - Allowed If this value is non-zero, then
+ * the HWRM shall allow the host SW driver to configure CoS Bandwidth
+ * configuration using hwrm_queue_cos2bw_cfg.
+ */
+ uint8_t queue_id0;
+ /* ID of CoS Queue 0. FF - Invalid id */
+ uint8_t queue_id0_service_profile;
+ /* This value is applicable to CoS queues only. */
+ /* Lossy (best-effort) */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSY UINT32_C(0x0)
+ /* Lossless */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1)
+ /* Set to 0xFF... (All Fs) if there is no service profile specified */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff)
+ uint8_t queue_id1;
+ /* ID of CoS Queue 1. FF - Invalid id */
+ uint8_t queue_id1_service_profile;
+ /* This value is applicable to CoS queues only. */
+ /* Lossy (best-effort) */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID1_SERVICE_PROFILE_LOSSY UINT32_C(0x0)
+ /* Lossless */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID1_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1)
+ /* Set to 0xFF... (All Fs) if there is no service profile specified */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID1_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff)
+ uint8_t queue_id2;
+ /* ID of CoS Queue 2. FF - Invalid id */
+ uint8_t queue_id2_service_profile;
+ /* This value is applicable to CoS queues only. */
+ /* Lossy (best-effort) */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID2_SERVICE_PROFILE_LOSSY UINT32_C(0x0)
+ /* Lossless */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID2_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1)
+ /* Set to 0xFF... (All Fs) if there is no service profile specified */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID2_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff)
+ uint8_t queue_id3;
+ /* ID of CoS Queue 3. FF - Invalid id */
+ uint8_t queue_id3_service_profile;
+ /* This value is applicable to CoS queues only. */
+ /* Lossy (best-effort) */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID3_SERVICE_PROFILE_LOSSY UINT32_C(0x0)
+ /* Lossless */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID3_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1)
+ /* Set to 0xFF... (All Fs) if there is no service profile specified */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID3_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff)
+ uint8_t queue_id4;
+ /* ID of CoS Queue 4. FF - Invalid id */
+ uint8_t queue_id4_service_profile;
+ /* This value is applicable to CoS queues only. */
+ /* Lossy (best-effort) */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID4_SERVICE_PROFILE_LOSSY UINT32_C(0x0)
+ /* Lossless */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID4_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1)
+ /* Set to 0xFF... (All Fs) if there is no service profile specified */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID4_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff)
+ uint8_t queue_id5;
+ /* ID of CoS Queue 5. FF - Invalid id */
+ uint8_t queue_id5_service_profile;
+ /* This value is applicable to CoS queues only. */
+ /* Lossy (best-effort) */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID5_SERVICE_PROFILE_LOSSY UINT32_C(0x0)
+ /* Lossless */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID5_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1)
+ /* Set to 0xFF... (All Fs) if there is no service profile specified */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID5_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff)
+ uint8_t queue_id6;
+ /* ID of CoS Queue 6. FF - Invalid id */
+ uint8_t queue_id6_service_profile;
+ /* This value is applicable to CoS queues only. */
+ /* Lossy (best-effort) */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID6_SERVICE_PROFILE_LOSSY UINT32_C(0x0)
+ /* Lossless */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID6_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1)
+ /* Set to 0xFF... (All Fs) if there is no service profile specified */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID6_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff)
+ uint8_t queue_id7;
+ /* ID of CoS Queue 7. FF - Invalid id */
+ uint8_t queue_id7_service_profile;
+ /* This value is applicable to CoS queues only. */
+ /* Lossy (best-effort) */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID7_SERVICE_PROFILE_LOSSY UINT32_C(0x0)
+ /* Lossless */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID7_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1)
+ /* Set to 0xFF... (All Fs) if there is no service profile specified */
+ #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID7_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff)
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_queue_qcfg */
+/*
+ * Description: This function is called by a driver to query a queue
+ * configuration.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_queue_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_QUEUE_QCFG_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_QUEUE_QCFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0)
+ /* rx path */
+ #define HWRM_QUEUE_QCFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1)
+ #define HWRM_QUEUE_QCFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_QCFG_INPUT_FLAGS_PATH_RX
+ uint32_t queue_id;
+ /* Queue ID of the queue. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_queue_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t queue_len;
+ /* This value is a the estimate packet length used in the TX arbiter. */
+ uint8_t service_profile;
+ /* This value is applicable to CoS queues only. */
+ /* Lossy (best-effort) */
+ #define HWRM_QUEUE_QCFG_OUTPUT_SERVICE_PROFILE_LOSSY UINT32_C(0x0)
+ /* Lossless */
+ #define HWRM_QUEUE_QCFG_OUTPUT_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1)
+ /* Set to 0xFF... (All Fs) if there is no service profile specified */
+ #define HWRM_QUEUE_QCFG_OUTPUT_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff)
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_queue_cfg */
+/* Description: This function is called by a driver to configure a queue. */
+/* Input (40 bytes) */
+
+struct hwrm_queue_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_QUEUE_CFG_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_QUEUE_CFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0)
+ /* rx path */
+ #define HWRM_QUEUE_CFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1)
+ #define HWRM_QUEUE_CFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_CFG_INPUT_FLAGS_PATH_RX
+ uint32_t enables;
+ /* This bit must be '1' for the dflt_len field to be configured. */
+ #define HWRM_QUEUE_CFG_INPUT_ENABLES_DFLT_LEN UINT32_C(0x1)
+ /* This bit must be '1' for the service_profile field to be configured. */
+ #define HWRM_QUEUE_CFG_INPUT_ENABLES_SERVICE_PROFILE UINT32_C(0x2)
+ uint32_t queue_id;
+ /* Queue ID of queue that is to be configured by this function. */
+ uint32_t dflt_len;
+ /*
+ * This value is a the estimate packet length used in the TX arbiter.
+ * Set to 0xFF... (All Fs) to not adjust this value.
+ */
+ uint8_t service_profile;
+ /* This value is applicable to CoS queues only. */
+ /* Lossy (best-effort) */
+ #define HWRM_QUEUE_CFG_INPUT_SERVICE_PROFILE_LOSSY UINT32_C(0x0)
+ /* Lossless */
+ #define HWRM_QUEUE_CFG_INPUT_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1)
+ /* Set to 0xFF... (All Fs) if there is no service profile specified */
+ #define HWRM_QUEUE_CFG_INPUT_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff)
+ uint8_t unused_0[7];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_queue_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_queue_buffers_qcfg */
+/*
+ * Description: This function is called by a driver to query configuration of
+ * the buffers assigned to a queue.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_queue_buffers_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_QUEUE_BUFFERS_QCFG_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_QUEUE_BUFFERS_QCFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0)
+ /* rx path */
+ #define HWRM_QUEUE_BUFFERS_QCFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1)
+ #define HWRM_QUEUE_BUFFERS_QCFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_BUFFERS_QCFG_INPUT_FLAGS_PATH_RX
+ uint32_t queue_id;
+ /* Queue ID of queue that is to be configured by this function. */
+} __attribute__((packed));
+
+/* Output (40 bytes) */
+
+struct hwrm_queue_buffers_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t reserved;
+ /* Number of bytes allocated as reserved space for this queue. */
+ uint32_t shared;
+ /*
+ * Number of bytes of shared buffer space for this queue. The changing
+ * of shared buffer size for one CoS may create an adverse effect on
+ * other CoSs sharing the same buffer. It is recommended that the driver
+ * does not modify the shared mbuf size without understanding the
+ * consequence of it.
+ */
+ uint32_t xoff;
+ /*
+ * XOFF threshold of the queue. This is a high threshold value used to
+ * trigger XOFF.
+ */
+ uint32_t xon;
+ /*
+ * XON threshold of the queue. This is the low threshold value used to
+ * trigger XON.
+ */
+ uint32_t full;
+ /*
+ * FULL threshold of the queue. At this threshold, buffers allocated for
+ * this queue are full. Once this condition is asserted, packets on that
+ * queue are dropped.
+ */
+ uint32_t notfull;
+ /*
+ * NOTFULL threshold of the queue. This threshold is used for the de-
+ * assertion of buffers full condition.
+ */
+ uint32_t max;
+ /*
+ * The maximum number of bytes that will be allowed to be consumed by
+ * the queue. This value is the sum of both the number of bytes reserved
+ * for this queue and the maximum number of bytes of shared buffers
+ * allowed to be consumed by this queue.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_queue_buffers_cfg */
+/*
+ * Description: This function is called by a driver to configure the buffering
+ * for a queue.
+ */
+/* Input (56 bytes) */
+
+struct hwrm_queue_buffers_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0)
+ /* rx path */
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1)
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_BUFFERS_CFG_INPUT_FLAGS_PATH_RX
+ uint32_t enables;
+ /* This bit must be '1' for the reserved field to be configured. */
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_RESERVED UINT32_C(0x1)
+ /* This bit must be '1' for the shared field to be configured. */
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_SHARED UINT32_C(0x2)
+ /* This bit must be '1' for the xoff field to be configured. */
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_XOFF UINT32_C(0x4)
+ /* This bit must be '1' for the xon field to be configured. */
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_XON UINT32_C(0x8)
+ /* This bit must be '1' for the full field to be configured. */
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_FULL UINT32_C(0x10)
+ /* This bit must be '1' for the notfull field to be configured. */
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_NOTFULL UINT32_C(0x20)
+ /* This bit must be '1' for the max field to be configured. */
+ #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_MAX UINT32_C(0x40)
+ uint32_t queue_id;
+ /* Queue ID of queue that is to be configured by this function. */
+ uint32_t reserved;
+ /* Number of bytes to be allocated as reserved space for this queue. */
+ uint32_t shared;
+ /*
+ * Number of bytes of shared buffer space for this queue. The changing
+ * of shared buffer size for one CoS may create an adverse effect on
+ * other CoSs sharing the same buffer. It is recommended that the driver
+ * does not modify the shared mbuf size without understanding the
+ * consequence of it.
+ */
+ uint32_t xoff;
+ /*
+ * XOFF threshold of the queue. This is a high threshold value used to
+ * trigger XOFF.
+ */
+ uint32_t xon;
+ /*
+ * XON threshold of the queue. This is the low threshold value used to
+ * trigger XON.
+ */
+ uint32_t full;
+ /*
+ * FULL threshold of the queue. At this threshold, buffers allocated for
+ * this queue are full. Once this condition is asserted, packets on that
+ * queue are dropped.
+ */
+ uint32_t notfull;
+ /*
+ * NOTFULL threshold of the queue. This threshold is used for the de-
+ * assertion of buffers full condition.
+ */
+ uint32_t max;
+ /*
+ * The maximum number of bytes that will be allowed to be consumed by
+ * the queue. This value is the sum of both the number of bytes reserved
+ * for this queue and the maximum number of bytes of shared buffers
+ * allowed to be consumed by this queue.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_queue_buffers_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_queue_pfcenable_qcfg */
+/*
+ * Description: This function is called by a driver to query PFC configuration
+ * for different priorities on that port. This mapping can be different on
+ * different ports.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_queue_pfcenable_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t port_id;
+ /*
+ * Port ID of port for which the table is being configured. The HWRM
+ * needs to check whether this function is allowed to configure pri2cos
+ * mapping on this port.
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_queue_pfcenable_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t flags;
+ /* If set to 1, then PFC is enabled on PRI 0. */
+ #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI0_PFC_ENABLED UINT32_C(0x1)
+ /* If set to 1, then PFC is enabled on PRI 1. */
+ #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI1_PFC_ENABLED UINT32_C(0x2)
+ /* If set to 1, then PFC is enabled on PRI 2. */
+ #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI2_PFC_ENABLED UINT32_C(0x4)
+ /* If set to 1, then PFC is enabled on PRI 3. */
+ #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI3_PFC_ENABLED UINT32_C(0x8)
+ /* If set to 1, then PFC is enabled on PRI 4. */
+ #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI4_PFC_ENABLED UINT32_C(0x10)
+ /* If set to 1, then PFC is enabled on PRI 5. */
+ #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI5_PFC_ENABLED UINT32_C(0x20)
+ /* If set to 1, then PFC is enabled on PRI 6. */
+ #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI6_PFC_ENABLED UINT32_C(0x40)
+ /* If set to 1, then PFC is enabled on PRI 7. */
+ #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI7_PFC_ENABLED UINT32_C(0x80)
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_queue_pfcenable_cfg */
+/*
+ * Description: This function is called by a driver to configure the PFC enabled
+ * for different priorities on that port. This mapping can be different on
+ * different ports.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_queue_pfcenable_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /* If set to 1, then PFC is requested to be enabled on PRI 0. */
+ #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI0_PFC_ENABLED UINT32_C(0x1)
+ /* If set to 1, then PFC is requested to be enabled on PRI 1. */
+ #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI1_PFC_ENABLED UINT32_C(0x2)
+ /* If set to 1, then PFC is requested to be enabled on PRI 2. */
+ #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI2_PFC_ENABLED UINT32_C(0x4)
+ /* If set to 1, then PFC is requested to be enabled on PRI 3. */
+ #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI3_PFC_ENABLED UINT32_C(0x8)
+ /* If set to 1, then PFC is requested to be enabled on PRI 4. */
+ #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI4_PFC_ENABLED UINT32_C(0x10)
+ /* If set to 1, then PFC is requested to be enabled on PRI 5. */
+ #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI5_PFC_ENABLED UINT32_C(0x20)
+ /* If set to 1, then PFC is requested to be enabled on PRI 6. */
+ #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI6_PFC_ENABLED UINT32_C(0x40)
+ /* If set to 1, then PFC is requested to be enabled on PRI 7. */
+ #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI7_PFC_ENABLED UINT32_C(0x80)
+ uint16_t port_id;
+ /*
+ * Port ID of port for which the table is being configured. The HWRM
+ * needs to check whether this function is allowed to configure pri2cos
+ * mapping on this port.
+ */
+ uint16_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_queue_pfcenable_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_queue_pri2cos_qcfg */
+/*
+ * Description: This function is called by a driver to query configuration of
+ * the priority to CoS queue mapping on the transmit side and receive side. This
+ * mapping can be different in each direction (TX or RX). This mapping can be
+ * different on different ports. Each CoS queue represents a Traffic Class (TC)
+ * on that port.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_queue_pri2cos_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX (UINT32_C(0x0) << 0)
+ /* rx path */
+ #define HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_RX (UINT32_C(0x1) << 0)
+ #define HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_RX
+ /*
+ * When this bit is set to '1', the mapping is requested for inner VLAN
+ * PRI.
+ */
+ #define HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_IVLAN UINT32_C(0x2)
+ uint8_t port_id;
+ /*
+ * Port ID of port for which the table is being configured. The HWRM
+ * needs to check whether this function is allowed to configure pri2cos
+ * mapping on this port.
+ */
+ uint8_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_queue_pri2cos_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t pri0_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 0. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri1_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 1. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri2_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 2 This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri3_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 3. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri4_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 4. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri5_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 5. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri6_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 6. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri7_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 7. This value can only be changed
+ * before traffic has started.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_queue_pri2cos_cfg */
+/*
+ * Description: This function is called by a driver to configure the priority to
+ * CoS queue mapping on the transmit side and receive side. This mapping can be
+ * different in each direction (TX or RX). This mapping can be different on
+ * different ports. Each CoS queue represents a Traffic Class (TC) on that port.
+ * This command configures the VLAN PRI-to-TC mapping for a specific port in
+ * specific direction.
+ */
+/* Input (40 bytes) */
+
+struct hwrm_queue_pri2cos_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_TX (UINT32_C(0x0) << 0)
+ /* rx path */
+ #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_RX (UINT32_C(0x1) << 0)
+ #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_RX
+ /* When this bit is '1', the mapping is for inner VLAN PRI. */
+ #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_IVLAN UINT32_C(0x2)
+ uint32_t enables;
+ uint8_t port_id;
+ /*
+ * Port ID of port for which the table is being configured. The HWRM
+ * needs to check whether this function is allowed to configure pri2cos
+ * mapping on this port.
+ */
+ uint8_t pri0_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 0. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri1_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 1. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri2_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 2 This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri3_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 3. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri4_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 4. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri5_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 5. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri6_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 6. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t pri7_cos_queue_id;
+ /*
+ * CoS Queue assigned to priority 7. This value can only be changed
+ * before traffic has started.
+ */
+ uint8_t unused_0[7];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_queue_pri2cos_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_queue_cos2bw_qcfg */
+/*
+ * Description: This function is called by a driver to query the BW to CoS queue
+ * mapping on the transmit side of a specific port. This mapping can be
+ * different on different ports. Each CoS queue represents a Traffic Class (TC)
+ * on that port. Each traffic class can be assigned a valid combination of the
+ * following: - Minimum bandwidth - Maximum bandwidth - Transmission selection
+ * algorithm (TSA) - Priority Level (only applies to strict priority COS) -
+ * Bandwidth weight # A CoS can be SP or non-SP: A SP CoS always gets the strict
+ * priority. Is an COS min BW is set to 0x0 then it is considered to be non-SP;
+ * this is a valid configuration. Note: SP provides lower latency in addition to
+ * reserved bandwidth # For both SP CoS and non-SP CoS, min BW can be specified
+ * to reserve specific amount of the port BW. # The min BW specified for a CoS
+ * shall not exceed max port bandwidth. # The total of min BWs specified for all
+ * CoS shall not exceed max port bandwidth. # For any non-SP CoS, the minimum
+ * bandwidth guarantees are subject to round-robin scheduling. This allows BW
+ * reservation with anti-starvation; one CoS will not block another CoS using
+ * RR. Note: The bandwidth guarantees for any non-SP CoS are met after servicing
+ * all SP CoS. # An SP CoS can potentially starve other lower priority SP CoS
+ * and non-SP CoS queues. This can occur to the extent the SP min exceeds the
+ * available port BW. # For any CoS, max BW can be specified to limit the BW
+ * consumed by the CoS. # The max BW specified for a CoS shall not exceed the
+ * max port bandwidth. # The WFQ provides a mechanism for sharing available
+ * bandwidth beyond the reserved minimums configured for each CoS. The WFQ
+ * scheduler is used to provide the percentages of remaining bandwidth after: *
+ * first servicing the reserved bandwidth for all SP CoS, * followed by the
+ * reserved bandwidth for all non-SP CoS * All CoS may participate in the WFQ #
+ * If a CoS does not have a configured max BW it may use all available bandwidth
+ * up to the max port bandwidth Minimum Bandwidth (min BW): # This is the
+ * guaranteed bandwidth for the COS. # A value of 0x0 is valid and it means that
+ * this COS is not guaranteed any bandwidth. A value of 0xFF.. (all Fs) means
+ * min BW is not specified. When the min BW is not specified, the HWRM can set
+ * it to any value it considers appropriate. Note: For a non-SP COS, the HWRM
+ * should set min BW to 0 when the min BW is not specified. For an SP COS, the
+ * HWRM should set min BW to some small value when the min BW is not specified.
+ * Maximum Bandwidth: # This is the bandwidth limit of the COS. # Values 0x0 and
+ * 0xFF.. (all Fs) are considered unspecified and the HWRM will set the maximum
+ * bandwidth to maximum port bandwidth. Priority Level: # It applies only to SP.
+ * # This parameter is ignored for non-SP. # 0-7 are valid values (higher value
+ * means higher priority) # A priority level can be assigned to at most one SP.
+ * # Invalid priority levels assignment for SPs shall result in failure.
+ * Additional notes: # The HWRM may have to use min and (max - min) to set
+ * appropriate counters of hardware rate limiters. # The bandwidth percentage as
+ * specified in the DCB TC BW assignment should be used by the driver to specify
+ * maximum bandwidth and bandwidth weight for a COS. For example, the driver
+ * should set max BW to 20 Gbps and weight to 50 for two COSs when these two
+ * COSs are assigned 50% share of 40 Gbps max port bandwidth.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_queue_cos2bw_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t port_id;
+ /*
+ * Port ID of port for which the table is being configured. The HWRM
+ * needs to check whether this function is allowed to configure TC BW
+ * assignment on this port.
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (112 bytes) */
+
+struct hwrm_queue_cos2bw_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t queue_id0;
+ /* ID of CoS Queue 0. */
+ uint8_t unused_0;
+ uint16_t unused_1;
+ uint32_t queue_id0_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id0_max_bw;
+ /*
+ * Maximum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id0_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id0_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id0_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id1;
+ /* ID of CoS Queue 1. */
+ uint32_t queue_id1_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id1_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id1_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID1_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID1_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID1_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID1_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id1_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id1_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id2;
+ /* ID of CoS Queue 2. */
+ uint32_t queue_id2_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id2_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id2_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID2_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID2_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID2_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID2_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id2_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id2_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id3;
+ /* ID of CoS Queue 3. */
+ uint32_t queue_id3_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id3_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id3_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID3_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID3_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID3_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID3_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id3_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id3_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id4;
+ /* ID of CoS Queue 4. */
+ uint32_t queue_id4_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id4_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id4_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID4_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID4_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID4_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID4_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id4_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id4_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id5;
+ /* ID of CoS Queue 5. */
+ uint32_t queue_id5_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id5_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id5_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID5_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID5_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID5_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID5_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id5_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id5_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id6;
+ /* ID of CoS Queue 6. */
+ uint32_t queue_id6_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id6_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id6_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID6_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID6_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID6_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID6_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id6_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id6_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id7;
+ /* ID of CoS Queue 7. */
+ uint32_t queue_id7_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id7_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id7_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID7_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID7_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID7_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID7_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id7_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id7_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t unused_5;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_queue_cos2bw_cfg */
+/*
+ * Description: This function is called by a driver to configure the BW to CoS
+ * queue mapping on the transmit side of a specific port. This mapping can be
+ * different on different ports. Each CoS queue represents a Traffic Class (TC)
+ * on that port. Each traffic class can be assigned a valid combination of the
+ * following: - Minimum bandwidth - Maximum bandwidth - Transmission selection
+ * algorithm (TSA) - Priority Level (only applies to strict priority COS) -
+ * Bandwidth weight # A CoS can be SP or non-SP: A SP CoS always gets the strict
+ * priority. Is an COS min BW is set to 0x0 then it is considered to be non-SP;
+ * this is a valid configuration. Note: SP provides lower latency in addition to
+ * reserved bandwidth # For both SP CoS and non-SP CoS, min BW can be specified
+ * to reserve specific amount of the port BW. # The min BW specified for a CoS
+ * shall not exceed max port bandwidth. # The total of min BWs specified for all
+ * CoS shall not exceed max port bandwidth. # For any non-SP CoS, the minimum
+ * bandwidth guarantees are subject to round-robin scheduling. This allows BW
+ * reservation with anti-starvation; one CoS will not block another CoS using
+ * RR. Note: The bandwidth guarantees for any non-SP CoS are met after servicing
+ * all SP CoS. # An SP CoS can potentially starve other lower priority SP CoS
+ * and non-SP CoS queues. This can occur to the extent the SP min exceeds the
+ * available port BW. # For any CoS, max BW can be specified to limit the BW
+ * consumed by the CoS. # The max BW specified for a CoS shall not exceed the
+ * max port bandwidth. # The WFQ provides a mechanism for sharing available
+ * bandwidth beyond the reserved minimums configured for each CoS. The WFQ
+ * scheduler is used to provide the percentages of remaining bandwidth after: -
+ * first servicing the reserved bandwidth for all SP CoS, - followed by the
+ * reserved bandwidth for all non-SP CoS - All CoS may participate in the WFQ #
+ * If a CoS does not have a configured max BW it may use all available bandwidth
+ * up to the max port bandwidth Minimum Bandwidth (min BW): # This is the
+ * guaranteed bandwidth for the COS. # A value of 0x0 is valid and it means that
+ * this COS is not guaranteed any bandwidth. A value of 0xFF.. (all Fs) means
+ * min BW is not specified. When the min BW is not specified, the HWRM can set
+ * it to any value it considers appropriate. Note: For a non-SP COS, the HWRM
+ * should set min BW to 0 when the min BW is not specified. For an SP COS, the
+ * HWRM should set min BW to some small value when the min BW is not specified.
+ * Maximum Bandwidth: # This is the bandwidth limit of the COS. # Values 0x0 and
+ * 0xFF.. (all Fs) are considered unspecified and the HWRM will set the maximum
+ * bandwidth to maximum port bandwidth. Priority Level: # It applies only to SP.
+ * # This parameter is ignored for non-SP. # 0-7 are valid values (higher value
+ * means higher priority) # A priority level can be assigned to at most one SP.
+ * # Invalid priority levels assignment for SPs shall result in failure.
+ * Additional notes: # The HWRM may have to use min and (max - min) to set
+ * appropriate counters of hardware rate limiters. # The bandwidth percentage as
+ * specified in the DCB TC BW assignment should be used by the driver to specify
+ * maximum bandwidth and bandwidth weight for a COS. For example, the driver
+ * should set max BW to 20 Gbps and weight to 50 for two COSs when these two
+ * COSs are assigned 50% share of 40 Gbps max port bandwidth.
+ */
+/* Input (128 bytes) */
+
+struct hwrm_queue_cos2bw_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ uint32_t enables;
+ /*
+ * This bit must be '1' for the cos_queue_id0_valid field to be
+ * configured.
+ */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID0_VALID UINT32_C(0x1)
+ /*
+ * This bit must be '1' for the cos_queue_id1_valid field to be
+ * configured.
+ */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID1_VALID UINT32_C(0x2)
+ /*
+ * This bit must be '1' for the cos_queue_id2_valid field to be
+ * configured.
+ */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID2_VALID UINT32_C(0x4)
+ /*
+ * This bit must be '1' for the cos_queue_id3_valid field to be
+ * configured.
+ */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID3_VALID UINT32_C(0x8)
+ /*
+ * This bit must be '1' for the cos_queue_id4_valid field to be
+ * configured.
+ */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID4_VALID UINT32_C(0x10)
+ /*
+ * This bit must be '1' for the cos_queue_id5_valid field to be
+ * configured.
+ */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID5_VALID UINT32_C(0x20)
+ /*
+ * This bit must be '1' for the cos_queue_id6_valid field to be
+ * configured.
+ */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID6_VALID UINT32_C(0x40)
+ /*
+ * This bit must be '1' for the cos_queue_id7_valid field to be
+ * configured.
+ */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID7_VALID UINT32_C(0x80)
+ uint16_t port_id;
+ /*
+ * Port ID of port for which the table is being configured. The HWRM
+ * needs to check whether this function is allowed to configure TC BW
+ * assignment on this port.
+ */
+ uint8_t queue_id0;
+ /* ID of CoS Queue 0. */
+ uint8_t unused_0;
+ uint32_t queue_id0_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id0_max_bw;
+ /*
+ * Maximum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id0_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID0_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID0_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID0_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID0_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id0_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id0_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id1;
+ /* ID of CoS Queue 1. */
+ uint32_t queue_id1_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id1_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id1_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID1_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID1_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID1_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID1_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id1_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id1_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id2;
+ /* ID of CoS Queue 2. */
+ uint32_t queue_id2_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id2_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id2_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID2_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID2_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID2_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID2_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id2_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id2_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id3;
+ /* ID of CoS Queue 3. */
+ uint32_t queue_id3_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id3_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id3_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID3_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID3_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID3_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID3_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id3_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id3_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id4;
+ /* ID of CoS Queue 4. */
+ uint32_t queue_id4_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id4_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id4_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID4_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID4_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID4_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID4_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id4_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id4_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id5;
+ /* ID of CoS Queue 5. */
+ uint32_t queue_id5_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id5_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id5_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID5_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID5_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID5_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID5_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id5_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id5_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id6;
+ /* ID of CoS Queue 6. */
+ uint32_t queue_id6_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id6_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id6_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID6_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID6_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID6_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID6_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id6_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id6_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t queue_id7;
+ /* ID of CoS Queue 7. */
+ uint32_t queue_id7_min_bw;
+ /*
+ * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint32_t queue_id7_max_bw;
+ /*
+ * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate
+ * this value into byte counter and time interval used for this COS
+ * inside the device.
+ */
+ uint8_t queue_id7_tsa_assign;
+ /* Transmission Selection Algorithm (TSA) for CoS Queue. */
+ /* Strict Priority */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID7_TSA_ASSIGN_SP UINT32_C(0x0)
+ /* Enhanced Transmission Selection */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID7_TSA_ASSIGN_ETS UINT32_C(0x1)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID7_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2)
+ /* reserved */
+ #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID7_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff)
+ uint8_t queue_id7_pri_lvl;
+ /*
+ * Priority level for strict priority. Valid only when the tsa_assign is
+ * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved.
+ */
+ uint8_t queue_id7_bw_weight;
+ /*
+ * Weight used to allocate remaining BW for this COS after servicing
+ * guaranteed bandwidths for all COS.
+ */
+ uint8_t unused_1[5];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_queue_cos2bw_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_alloc */
+/*
+ * Description: This VNIC is a resource in the RX side of the chip that is used
+ * to represent a virtual host "interface". # At the time of VNIC allocation or
+ * configuration, the function can specify whether it wants the requested VNIC
+ * to be the default VNIC for the function or not. # If a function requests
+ * allocation of a VNIC for the first time and a VNIC is successfully allocated
+ * by the HWRM, then the HWRM shall make the allocated VNIC as the default VNIC
+ * for that function. # The default VNIC shall be used for the default action
+ * for a partition or function. # For each VNIC allocated on a function, a
+ * mapping on the RX side to map the allocated VNIC to source virtual interface
+ * shall be performed by the HWRM. This should be hidden to the function driver
+ * requesting the VNIC allocation. This enables broadcast/multicast replication
+ * with source knockout. # If multicast replication with source knockout is
+ * enabled, then the internal VNIC to SVIF mapping data structures shall be
+ * programmed at the time of VNIC allocation.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_vnic_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * When this bit is '1', this VNIC is requested to be the default VNIC
+ * for this function.
+ */
+ #define HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT UINT32_C(0x1)
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_vnic_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t vnic_id;
+ /* Logical vnic ID */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_free */
+/*
+ * Description: Free a VNIC resource. Idle any resources associated with the
+ * VNIC as well as the VNIC. Reset and release all resources associated with the
+ * VNIC.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_vnic_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t vnic_id;
+ /* Logical vnic ID */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_vnic_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_cfg */
+/* Description: Configure the RX VNIC structure. */
+/* Input (40 bytes) */
+
+struct hwrm_vnic_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * When this bit is '1', the VNIC is requested to be the default VNIC
+ * for the function.
+ */
+ #define HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT UINT32_C(0x1)
+ /*
+ * When this bit is '1', the VNIC is being configured to strip VLAN in
+ * the RX path. If set to '0', then VLAN stripping is disabled on this
+ * VNIC.
+ */
+ #define HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE UINT32_C(0x2)
+ /*
+ * When this bit is '1', the VNIC is being configured to buffer receive
+ * packets in the hardware until the host posts new receive buffers. If
+ * set to '0', then bd_stall is being configured to be disabled on this
+ * VNIC.
+ */
+ #define HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE UINT32_C(0x4)
+ /*
+ * When this bit is '1', the VNIC is being configured to receive both
+ * RoCE and non-RoCE traffic. If set to '0', then this VNIC is not
+ * configured to be operating in dual VNIC mode.
+ */
+ #define HWRM_VNIC_CFG_INPUT_FLAGS_ROCE_DUAL_VNIC_MODE UINT32_C(0x8)
+ /*
+ * When this flag is set to '1', the VNIC is requested to be configured
+ * to receive only RoCE traffic. If this flag is set to '0', then this
+ * flag shall be ignored by the HWRM. If roce_dual_vnic_mode flag is set
+ * to '1', then the HWRM client shall not set this flag to '1'.
+ */
+ #define HWRM_VNIC_CFG_INPUT_FLAGS_ROCE_ONLY_VNIC_MODE UINT32_C(0x10)
+ /*
+ * When a VNIC uses one destination ring group for certain application
+ * (e.g. Receive Flow Steering) where exact match is used to direct
+ * packets to a VNIC with one destination ring group only, there is no
+ * need to configure RSS indirection table for that VNIC as only one
+ * destination ring group is used. This flag is used to enable a mode
+ * where RSS is enabled in the VNIC using a RSS context for computing
+ * RSS hash but the RSS indirection table is not configured using
+ * hwrm_vnic_rss_cfg. If this mode is enabled, then the driver should
+ * not program RSS indirection table for the RSS context that is used
+ * for computing RSS hash only.
+ */
+ #define HWRM_VNIC_CFG_INPUT_FLAGS_RSS_DFLT_CR_MODE UINT32_C(0x20)
+ uint32_t enables;
+ /* This bit must be '1' for the dflt_ring_grp field to be configured. */
+ #define HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP UINT32_C(0x1)
+ /* This bit must be '1' for the rss_rule field to be configured. */
+ #define HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE UINT32_C(0x2)
+ /* This bit must be '1' for the cos_rule field to be configured. */
+ #define HWRM_VNIC_CFG_INPUT_ENABLES_COS_RULE UINT32_C(0x4)
+ /* This bit must be '1' for the lb_rule field to be configured. */
+ #define HWRM_VNIC_CFG_INPUT_ENABLES_LB_RULE UINT32_C(0x8)
+ /* This bit must be '1' for the mru field to be configured. */
+ #define HWRM_VNIC_CFG_INPUT_ENABLES_MRU UINT32_C(0x10)
+ uint16_t vnic_id;
+ /* Logical vnic ID */
+ uint16_t dflt_ring_grp;
+ /*
+ * Default Completion ring for the VNIC. This ring will be chosen if
+ * packet does not match any RSS rules and if there is no COS rule.
+ */
+ uint16_t rss_rule;
+ /*
+ * RSS ID for RSS rule/table structure. 0xFF... (All Fs) if there is no
+ * RSS rule.
+ */
+ uint16_t cos_rule;
+ /*
+ * RSS ID for COS rule/table structure. 0xFF... (All Fs) if there is no
+ * COS rule.
+ */
+ uint16_t lb_rule;
+ /*
+ * RSS ID for load balancing rule/table structure. 0xFF... (All Fs) if
+ * there is no LB rule.
+ */
+ uint16_t mru;
+ /*
+ * The maximum receive unit of the vnic. Each vnic is associated with a
+ * function. The vnic mru value overwrites the mru setting of the
+ * associated function. The HWRM shall make sure that vnic mru does not
+ * exceed the mru of the port the function is associated with.
+ */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_vnic_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_qcfg */
+/*
+ * Description: Query the RX VNIC structure. This function can be used by a PF
+ * driver to query its own VNIC resource or VNIC resource of its child VF. This
+ * function can also be used by a VF driver to query its own VNIC resource.
+ */
+/* Input (32 bytes) */
+
+struct hwrm_vnic_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the vf_id_valid field to be configured. */
+ #define HWRM_VNIC_QCFG_INPUT_ENABLES_VF_ID_VALID UINT32_C(0x1)
+ uint32_t vnic_id;
+ /* Logical vnic ID */
+ uint16_t vf_id;
+ /* ID of Virtual Function whose VNIC resource is being queried. */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (32 bytes) */
+
+struct hwrm_vnic_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t dflt_ring_grp;
+ /* Default Completion ring for the VNIC. */
+ uint16_t rss_rule;
+ /*
+ * RSS ID for RSS rule/table structure. 0xFF... (All Fs) if there is no
+ * RSS rule.
+ */
+ uint16_t cos_rule;
+ /*
+ * RSS ID for COS rule/table structure. 0xFF... (All Fs) if there is no
+ * COS rule.
+ */
+ uint16_t lb_rule;
+ /*
+ * RSS ID for load balancing rule/table structure. 0xFF... (All Fs) if
+ * there is no LB rule.
+ */
+ uint16_t mru;
+ /* The maximum receive unit of the vnic. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint32_t flags;
+ /* When this bit is '1', the VNIC is the default VNIC for the function. */
+ #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_DEFAULT UINT32_C(0x1)
+ /*
+ * When this bit is '1', the VNIC is configured to strip VLAN in the RX
+ * path. If set to '0', then VLAN stripping is disabled on this VNIC.
+ */
+ #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_VLAN_STRIP_MODE UINT32_C(0x2)
+ /*
+ * When this bit is '1', the VNIC is configured to buffer receive
+ * packets in the hardware until the host posts new receive buffers. If
+ * set to '0', then bd_stall is disabled on this VNIC.
+ */
+ #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_BD_STALL_MODE UINT32_C(0x4)
+ /*
+ * When this bit is '1', the VNIC is configured to receive both RoCE and
+ * non-RoCE traffic. If set to '0', then this VNIC is not configured to
+ * operate in dual VNIC mode.
+ */
+ #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_ROCE_DUAL_VNIC_MODE UINT32_C(0x8)
+ /*
+ * When this flag is set to '1', the VNIC is configured to receive only
+ * RoCE traffic. When this flag is set to '0', the VNIC is not
+ * configured to receive only RoCE traffic. If roce_dual_vnic_mode flag
+ * and this flag both are set to '1', then it is an invalid
+ * configuration of the VNIC. The HWRM should not allow that type of
+ * mis-configuration by HWRM clients.
+ */
+ #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_ROCE_ONLY_VNIC_MODE UINT32_C(0x10)
+ /*
+ * When a VNIC uses one destination ring group for certain application
+ * (e.g. Receive Flow Steering) where exact match is used to direct
+ * packets to a VNIC with one destination ring group only, there is no
+ * need to configure RSS indirection table for that VNIC as only one
+ * destination ring group is used. When this bit is set to '1', then the
+ * VNIC is enabled in a mode where RSS is enabled in the VNIC using a
+ * RSS context for computing RSS hash but the RSS indirection table is
+ * not configured.
+ */
+ #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_RSS_DFLT_CR_MODE UINT32_C(0x20)
+ uint32_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t unused_5;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_qcaps */
+/*
+ * Description: This function is used to query the capabilities of VNIC
+ * resources.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_vnic_qcaps_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_vnic_qcaps_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t mru;
+ /* The maximum receive unit that is settable on a vnic. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint32_t flags;
+ /* Unused. */
+ /*
+ * When this bit is '1', the capability of stripping VLAN in the RX path
+ * is supported on VNIC(s). If set to '0', then VLAN stripping
+ * capability is not supported on VNIC(s).
+ */
+ #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_VLAN_STRIP_CAP UINT32_C(0x2)
+ /*
+ * When this bit is '1', the capability to buffer receive packets in the
+ * hardware until the host posts new receive buffers is supported on
+ * VNIC(s). If set to '0', then bd_stall capability is not supported on
+ * VNIC(s).
+ */
+ #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_BD_STALL_CAP UINT32_C(0x4)
+ /*
+ * When this bit is '1', the capability to receive both RoCE and non-
+ * RoCE traffic on VNIC(s) is supported. If set to '0', then the
+ * capability to receive both RoCE and non-RoCE traffic on VNIC(s) is
+ * not supported.
+ */
+ #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_ROCE_DUAL_VNIC_CAP UINT32_C(0x8)
+ /*
+ * When this bit is set to '1', the capability to configure a VNIC to
+ * receive only RoCE traffic is supported. When this flag is set to '0',
+ * the VNIC capability to configure to receive only RoCE traffic is not
+ * supported.
+ */
+ #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_ROCE_ONLY_VNIC_CAP UINT32_C(0x10)
+ /*
+ * When this bit is set to '1', then the capability to enable a VNIC in
+ * a mode where RSS context without configuring RSS indirection table is
+ * supported (for RSS hash computation). When this bit is set to '0',
+ * then a VNIC can not be configured with a mode to enable RSS context
+ * without configuring RSS indirection table.
+ */
+ #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_RSS_DFLT_CR_CAP UINT32_C(0x20)
+ uint32_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t unused_5;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_tpa_cfg */
+/* Description: This function is used to enable/configure TPA on the VNIC. */
+/* Input (40 bytes) */
+
+struct hwrm_vnic_tpa_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * When this bit is '1', the VNIC shall be configured to perform
+ * transparent packet aggregation (TPA) of non-tunneled TCP packets.
+ */
+ #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA UINT32_C(0x1)
+ /*
+ * When this bit is '1', the VNIC shall be configured to perform
+ * transparent packet aggregation (TPA) of tunneled TCP packets.
+ */
+ #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA UINT32_C(0x2)
+ /*
+ * When this bit is '1', the VNIC shall be configured to perform
+ * transparent packet aggregation (TPA) according to Windows Receive
+ * Segment Coalescing (RSC) rules.
+ */
+ #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE UINT32_C(0x4)
+ /*
+ * When this bit is '1', the VNIC shall be configured to perform
+ * transparent packet aggregation (TPA) according to Linux Generic
+ * Receive Offload (GRO) rules.
+ */
+ #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO UINT32_C(0x8)
+ /*
+ * When this bit is '1', the VNIC shall be configured to perform
+ * transparent packet aggregation (TPA) for TCP packets with IP ECN set
+ * to non-zero.
+ */
+ #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN UINT32_C(0x10)
+ /*
+ * When this bit is '1', the VNIC shall be configured to perform
+ * transparent packet aggregation (TPA) for GRE tunneled TCP packets
+ * only if all packets have the same GRE sequence.
+ */
+ #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ UINT32_C(0x20)
+ /*
+ * When this bit is '1' and the GRO mode is enabled, the VNIC shall be
+ * configured to perform transparent packet aggregation (TPA) for
+ * TCP/IPv4 packets with consecutively increasing IPIDs. In other words,
+ * the last packet that is being aggregated to an already existing
+ * aggregation context shall have IPID 1 more than the IPID of the last
+ * packet that was aggregated in that aggregation context.
+ */
+ #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO_IPID_CHECK UINT32_C(0x40)
+ /*
+ * When this bit is '1' and the GRO mode is enabled, the VNIC shall be
+ * configured to perform transparent packet aggregation (TPA) for TCP
+ * packets with the same TTL (IPv4) or Hop limit (IPv6) value.
+ */
+ #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO_TTL_CHECK UINT32_C(0x80)
+ uint32_t enables;
+ /* This bit must be '1' for the max_agg_segs field to be configured. */
+ #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS UINT32_C(0x1)
+ /* This bit must be '1' for the max_aggs field to be configured. */
+ #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS UINT32_C(0x2)
+ /* This bit must be '1' for the max_agg_timer field to be configured. */
+ #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_TIMER UINT32_C(0x4)
+ /* This bit must be '1' for the min_agg_len field to be configured. */
+ #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN UINT32_C(0x8)
+ uint16_t vnic_id;
+ /* Logical vnic ID */
+ uint16_t max_agg_segs;
+ /*
+ * This is the maximum number of TCP segments that can be aggregated
+ * (unit is Log2). Max value is 31.
+ */
+ /* 1 segment */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_1 UINT32_C(0x0)
+ /* 2 segments */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_2 UINT32_C(0x1)
+ /* 4 segments */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_4 UINT32_C(0x2)
+ /* 8 segments */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_8 UINT32_C(0x3)
+ /* Any segment size larger than this is not valid */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX UINT32_C(0x1f)
+ uint16_t max_aggs;
+ /*
+ * This is the maximum number of aggregations this VNIC is allowed (unit
+ * is Log2). Max value is 7
+ */
+ /* 1 aggregation */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_1 UINT32_C(0x0)
+ /* 2 aggregations */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_2 UINT32_C(0x1)
+ /* 4 aggregations */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_4 UINT32_C(0x2)
+ /* 8 aggregations */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_8 UINT32_C(0x3)
+ /* 16 aggregations */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_16 UINT32_C(0x4)
+ /* Any aggregation size larger than this is not valid */
+ #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX UINT32_C(0x7)
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint32_t max_agg_timer;
+ /*
+ * This is the maximum amount of time allowed for an aggregation context
+ * to complete after it was initiated.
+ */
+ uint32_t min_agg_len;
+ /*
+ * This is the minimum amount of payload length required to start an
+ * aggregation context.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_vnic_tpa_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_tpa_qcfg */
+/*
+ * Description: This function can be used to query TPA configuration on the
+ * VNIC.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_vnic_tpa_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t vnic_id;
+ /* Logical vnic ID */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (32 bytes) */
+
+struct hwrm_vnic_tpa_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t flags;
+ /*
+ * When this bit is '1', the VNIC is configured to perform transparent
+ * packet aggregation (TPA) of non-tunneled TCP packets.
+ */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_TPA UINT32_C(0x1)
+ /*
+ * When this bit is '1', the VNIC is configured to perform transparent
+ * packet aggregation (TPA) of tunneled TCP packets.
+ */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_ENCAP_TPA UINT32_C(0x2)
+ /*
+ * When this bit is '1', the VNIC is configured to perform transparent
+ * packet aggregation (TPA) according to Windows Receive Segment
+ * Coalescing (RSC) rules.
+ */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_RSC_WND_UPDATE UINT32_C(0x4)
+ /*
+ * When this bit is '1', the VNIC is configured to perform transparent
+ * packet aggregation (TPA) according to Linux Generic Receive Offload
+ * (GRO) rules.
+ */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_GRO UINT32_C(0x8)
+ /*
+ * When this bit is '1', the VNIC is configured to perform transparent
+ * packet aggregation (TPA) for TCP packets with IP ECN set to non-zero.
+ */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_AGG_WITH_ECN UINT32_C(0x10)
+ /*
+ * When this bit is '1', the VNIC is configured to perform transparent
+ * packet aggregation (TPA) for GRE tunneled TCP packets only if all
+ * packets have the same GRE sequence.
+ */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ UINT32_C(0x20)
+ /*
+ * When this bit is '1' and the GRO mode is enabled, the VNIC is
+ * configured to perform transparent packet aggregation (TPA) for
+ * TCP/IPv4 packets with consecutively increasing IPIDs. In other words,
+ * the last packet that is being aggregated to an already existing
+ * aggregation context shall have IPID 1 more than the IPID of the last
+ * packet that was aggregated in that aggregation context.
+ */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_GRO_IPID_CHECK UINT32_C(0x40)
+ /*
+ * When this bit is '1' and the GRO mode is enabled, the VNIC is
+ * configured to perform transparent packet aggregation (TPA) for TCP
+ * packets with the same TTL (IPv4) or Hop limit (IPv6) value.
+ */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_GRO_TTL_CHECK UINT32_C(0x80)
+ uint16_t max_agg_segs;
+ /*
+ * This is the maximum number of TCP segments that can be aggregated
+ * (unit is Log2). Max value is 31.
+ */
+ /* 1 segment */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGG_SEGS_1 UINT32_C(0x0)
+ /* 2 segments */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGG_SEGS_2 UINT32_C(0x1)
+ /* 4 segments */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGG_SEGS_4 UINT32_C(0x2)
+ /* 8 segments */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGG_SEGS_8 UINT32_C(0x3)
+ /* Any segment size larger than this is not valid */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGG_SEGS_MAX UINT32_C(0x1f)
+ uint16_t max_aggs;
+ /*
+ * This is the maximum number of aggregations this VNIC is allowed (unit
+ * is Log2). Max value is 7
+ */
+ /* 1 aggregation */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_1 UINT32_C(0x0)
+ /* 2 aggregations */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_2 UINT32_C(0x1)
+ /* 4 aggregations */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_4 UINT32_C(0x2)
+ /* 8 aggregations */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_8 UINT32_C(0x3)
+ /* 16 aggregations */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_16 UINT32_C(0x4)
+ /* Any aggregation size larger than this is not valid */
+ #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_MAX UINT32_C(0x7)
+ uint32_t max_agg_timer;
+ /*
+ * This is the maximum amount of time allowed for an aggregation context
+ * to complete after it was initiated.
+ */
+ uint32_t min_agg_len;
+ /*
+ * This is the minimum amount of payload length required to start an
+ * aggregation context.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_rss_cfg */
+/* Description: This function is used to enable RSS configuration. */
+/* Input (48 bytes) */
+
+struct hwrm_vnic_rss_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t hash_type;
+ /*
+ * When this bit is '1', the RSS hash shall be computed over source and
+ * destination IPv4 addresses of IPv4 packets.
+ */
+ #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 UINT32_C(0x1)
+ /*
+ * When this bit is '1', the RSS hash shall be computed over
+ * source/destination IPv4 addresses and source/destination ports of
+ * TCP/IPv4 packets.
+ */
+ #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4 UINT32_C(0x2)
+ /*
+ * When this bit is '1', the RSS hash shall be computed over
+ * source/destination IPv4 addresses and source/destination ports of
+ * UDP/IPv4 packets.
+ */
+ #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4 UINT32_C(0x4)
+ /*
+ * When this bit is '1', the RSS hash shall be computed over source and
+ * destination IPv4 addresses of IPv6 packets.
+ */
+ #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6 UINT32_C(0x8)
+ /*
+ * When this bit is '1', the RSS hash shall be computed over
+ * source/destination IPv6 addresses and source/destination ports of
+ * TCP/IPv6 packets.
+ */
+ #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6 UINT32_C(0x10)
+ /*
+ * When this bit is '1', the RSS hash shall be computed over
+ * source/destination IPv6 addresses and source/destination ports of
+ * UDP/IPv6 packets.
+ */
+ #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6 UINT32_C(0x20)
+ uint32_t unused_0;
+ uint64_t ring_grp_tbl_addr;
+ /* This is the address for rss ring group table */
+ uint64_t hash_key_tbl_addr;
+ /* This is the address for rss hash key table */
+ uint16_t rss_ctx_idx;
+ /* Index to the rss indirection table. */
+ uint16_t unused_1[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_vnic_rss_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_rss_qcfg */
+/* Description: This function is used to query RSS context configuration. */
+/* Input (24 bytes) */
+
+struct hwrm_vnic_rss_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t rss_ctx_idx;
+ /* Index to the rss indirection table. */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (64 bytes) */
+
+struct hwrm_vnic_rss_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t hash_type;
+ /*
+ * When this bit is '1', the RSS hash shall be computed over source and
+ * destination IPv4 addresses of IPv4 packets.
+ */
+ #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_IPV4 UINT32_C(0x1)
+ /*
+ * When this bit is '1', the RSS hash shall be computed over
+ * source/destination IPv4 addresses and source/destination ports of
+ * TCP/IPv4 packets.
+ */
+ #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_TCP_IPV4 UINT32_C(0x2)
+ /*
+ * When this bit is '1', the RSS hash shall be computed over
+ * source/destination IPv4 addresses and source/destination ports of
+ * UDP/IPv4 packets.
+ */
+ #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_UDP_IPV4 UINT32_C(0x4)
+ /*
+ * When this bit is '1', the RSS hash shall be computed over source and
+ * destination IPv4 addresses of IPv6 packets.
+ */
+ #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_IPV6 UINT32_C(0x8)
+ /*
+ * When this bit is '1', the RSS hash shall be computed over
+ * source/destination IPv6 addresses and source/destination ports of
+ * TCP/IPv6 packets.
+ */
+ #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_TCP_IPV6 UINT32_C(0x10)
+ /*
+ * When this bit is '1', the RSS hash shall be computed over
+ * source/destination IPv6 addresses and source/destination ports of
+ * UDP/IPv6 packets.
+ */
+ #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_UDP_IPV6 UINT32_C(0x20)
+ uint32_t unused_0;
+ uint32_t hash_key[10];
+ /* This is the value of rss hash key */
+ uint32_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_plcmodes_cfg */
+/*
+ * Description: This function can be used to set placement mode configuration of
+ * the VNIC.
+ */
+/* Input (40 bytes) */
+
+struct hwrm_vnic_plcmodes_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * When this bit is '1', the VNIC shall be configured to use regular
+ * placement algorithm. By default, the regular placement algorithm
+ * shall be enabled on the VNIC.
+ */
+ #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_REGULAR_PLACEMENT UINT32_C(0x1)
+ /*
+ * When this bit is '1', the VNIC shall be configured use the jumbo
+ * placement algorithm.
+ */
+ #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_JUMBO_PLACEMENT UINT32_C(0x2)
+ /*
+ * When this bit is '1', the VNIC shall be configured to enable Header-
+ * Data split for IPv4 packets according to the following rules: # If
+ * the packet is identified as TCP/IPv4, then the packet is split at the
+ * beginning of the TCP payload. # If the packet is identified as
+ * UDP/IPv4, then the packet is split at the beginning of UDP payload. #
+ * If the packet is identified as non-TCP and non-UDP IPv4 packet, then
+ * the packet is split at the beginning of the upper layer protocol
+ * header carried in the IPv4 packet.
+ */
+ #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_HDS_IPV4 UINT32_C(0x4)
+ /*
+ * When this bit is '1', the VNIC shall be configured to enable Header-
+ * Data split for IPv6 packets according to the following rules: # If
+ * the packet is identified as TCP/IPv6, then the packet is split at the
+ * beginning of the TCP payload. # If the packet is identified as
+ * UDP/IPv6, then the packet is split at the beginning of UDP payload. #
+ * If the packet is identified as non-TCP and non-UDP IPv6 packet, then
+ * the packet is split at the beginning of the upper layer protocol
+ * header carried in the IPv6 packet.
+ */
+ #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_HDS_IPV6 UINT32_C(0x8)
+ /*
+ * When this bit is '1', the VNIC shall be configured to enable Header-
+ * Data split for FCoE packets at the beginning of FC payload.
+ */
+ #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_HDS_FCOE UINT32_C(0x10)
+ /*
+ * When this bit is '1', the VNIC shall be configured to enable Header-
+ * Data split for RoCE packets at the beginning of RoCE payload (after
+ * BTH/GRH headers).
+ */
+ #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_HDS_ROCE UINT32_C(0x20)
+ uint32_t enables;
+ /*
+ * This bit must be '1' for the jumbo_thresh_valid field to be
+ * configured.
+ */
+ #define HWRM_VNIC_PLCMODES_CFG_INPUT_ENABLES_JUMBO_THRESH_VALID UINT32_C(0x1)
+ /* This bit must be '1' for the hds_offset_valid field to be configured. */
+ #define HWRM_VNIC_PLCMODES_CFG_INPUT_ENABLES_HDS_OFFSET_VALID UINT32_C(0x2)
+ /*
+ * This bit must be '1' for the hds_threshold_valid field to be
+ * configured.
+ */
+ #define HWRM_VNIC_PLCMODES_CFG_INPUT_ENABLES_HDS_THRESHOLD_VALID UINT32_C(0x4)
+ uint32_t vnic_id;
+ /* Logical vnic ID */
+ uint16_t jumbo_thresh;
+ /*
+ * When jumbo placement algorithm is enabled, this value is used to
+ * determine the threshold for jumbo placement. Packets with length
+ * larger than this value will be placed according to the jumbo
+ * placement algorithm.
+ */
+ uint16_t hds_offset;
+ /*
+ * This value is used to determine the offset into packet buffer where
+ * the split data (payload) will be placed according to one of of HDS
+ * placement algorithm. The lengths of packet buffers provided for split
+ * data shall be larger than this value.
+ */
+ uint16_t hds_threshold;
+ /*
+ * When one of the HDS placement algorithm is enabled, this value is
+ * used to determine the threshold for HDS placement. Packets with
+ * length larger than this value will be placed according to the HDS
+ * placement algorithm. This value shall be in multiple of 4 bytes.
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_vnic_plcmodes_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_plcmodes_qcfg */
+/*
+ * Description: This function can be used to query placement mode configuration
+ * of the VNIC.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_vnic_plcmodes_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t vnic_id;
+ /* Logical vnic ID */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_vnic_plcmodes_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t flags;
+ /*
+ * When this bit is '1', the VNIC is configured to use regular placement
+ * algorithm.
+ */
+ #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_REGULAR_PLACEMENT UINT32_C(0x1)
+ /*
+ * When this bit is '1', the VNIC is configured to use the jumbo
+ * placement algorithm.
+ */
+ #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_JUMBO_PLACEMENT UINT32_C(0x2)
+ /*
+ * When this bit is '1', the VNIC is configured to enable Header-Data
+ * split for IPv4 packets.
+ */
+ #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_HDS_IPV4 UINT32_C(0x4)
+ /*
+ * When this bit is '1', the VNIC is configured to enable Header-Data
+ * split for IPv6 packets.
+ */
+ #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_HDS_IPV6 UINT32_C(0x8)
+ /*
+ * When this bit is '1', the VNIC is configured to enable Header-Data
+ * split for FCoE packets.
+ */
+ #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_HDS_FCOE UINT32_C(0x10)
+ /*
+ * When this bit is '1', the VNIC is configured to enable Header-Data
+ * split for RoCE packets.
+ */
+ #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_HDS_ROCE UINT32_C(0x20)
+ /*
+ * When this bit is '1', the VNIC is configured to be the default VNIC
+ * of the requesting function.
+ */
+ #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_DFLT_VNIC UINT32_C(0x40)
+ uint16_t jumbo_thresh;
+ /*
+ * When jumbo placement algorithm is enabled, this value is used to
+ * determine the threshold for jumbo placement. Packets with length
+ * larger than this value will be placed according to the jumbo
+ * placement algorithm.
+ */
+ uint16_t hds_offset;
+ /*
+ * This value is used to determine the offset into packet buffer where
+ * the split data (payload) will be placed according to one of of HDS
+ * placement algorithm. The lengths of packet buffers provided for split
+ * data shall be larger than this value.
+ */
+ uint16_t hds_threshold;
+ /*
+ * When one of the HDS placement algorithm is enabled, this value is
+ * used to determine the threshold for HDS placement. Packets with
+ * length larger than this value will be placed according to the HDS
+ * placement algorithm. This value shall be in multiple of 4 bytes.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_rss_cos_lb_ctx_alloc */
+/* Description: This function is used to allocate COS/Load Balance context. */
+/* Input (16 bytes) */
+
+struct hwrm_vnic_rss_cos_lb_ctx_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_vnic_rss_cos_lb_ctx_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t rss_cos_lb_ctx_id;
+ /* rss_cos_lb_ctx_id is 16 b */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_vnic_rss_cos_lb_ctx_free */
+/* Description: This function can be used to free COS/Load Balance context. */
+/* Input (24 bytes) */
+
+struct hwrm_vnic_rss_cos_lb_ctx_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t rss_cos_lb_ctx_id;
+ /* rss_cos_lb_ctx_id is 16 b */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_vnic_rss_cos_lb_ctx_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_ring_alloc */
+/*
+ * Description: This command allocates and does basic preparation for a ring.
+ */
+/* Input (80 bytes) */
+
+struct hwrm_ring_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the Reserved1 field to be configured. */
+ #define HWRM_RING_ALLOC_INPUT_ENABLES_RESERVED1 UINT32_C(0x1)
+ /* This bit must be '1' for the Reserved2 field to be configured. */
+ #define HWRM_RING_ALLOC_INPUT_ENABLES_RESERVED2 UINT32_C(0x2)
+ /* This bit must be '1' for the Reserved3 field to be configured. */
+ #define HWRM_RING_ALLOC_INPUT_ENABLES_RESERVED3 UINT32_C(0x4)
+ /*
+ * This bit must be '1' for the stat_ctx_id_valid field to be
+ * configured.
+ */
+ #define HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID UINT32_C(0x8)
+ /* This bit must be '1' for the Reserved4 field to be configured. */
+ #define HWRM_RING_ALLOC_INPUT_ENABLES_RESERVED4 UINT32_C(0x10)
+ /* This bit must be '1' for the max_bw_valid field to be configured. */
+ #define HWRM_RING_ALLOC_INPUT_ENABLES_MAX_BW_VALID UINT32_C(0x20)
+ uint8_t ring_type;
+ /* Ring Type. */
+ /* Completion Ring (CR) */
+ #define HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL UINT32_C(0x0)
+ /* TX Ring (TR) */
+ #define HWRM_RING_ALLOC_INPUT_RING_TYPE_TX UINT32_C(0x1)
+ /* RX Ring (RR) */
+ #define HWRM_RING_ALLOC_INPUT_RING_TYPE_RX UINT32_C(0x2)
+ uint8_t unused_0;
+ uint16_t unused_1;
+ uint64_t page_tbl_addr;
+ /* This value is a pointer to the page table for the Ring. */
+ uint32_t fbo;
+ /* First Byte Offset of the first entry in the first page. */
+ uint8_t page_size;
+ /*
+ * Actual page size in 2^page_size. The supported range is increments in
+ * powers of 2 from 16 bytes to 1GB. - 4 = 16 B Page size is 16 B. - 12
+ * = 4 KB Page size is 4 KB. - 13 = 8 KB Page size is 8 KB. - 16 = 64 KB
+ * Page size is 64 KB. - 21 = 2 MB Page size is 2 MB. - 22 = 4 MB Page
+ * size is 4 MB. - 30 = 1 GB Page size is 1 GB.
+ */
+ uint8_t page_tbl_depth;
+ /*
+ * This value indicates the depth of page table. For this version of the
+ * specification, value other than 0 or 1 shall be considered as an
+ * invalid value. When the page_tbl_depth = 0, then it is treated as a
+ * special case with the following. 1. FBO and page size fields are not
+ * valid. 2. page_tbl_addr is the physical address of the first element
+ * of the ring.
+ */
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint32_t length;
+ /*
+ * Number of 16B units in the ring. Minimum size for a ring is 16 16B
+ * entries.
+ */
+ uint16_t logical_id;
+ /*
+ * Logical ring number for the ring to be allocated. This value
+ * determines the position in the doorbell area where the update to the
+ * ring will be made. For completion rings, this value is also the MSI-X
+ * vector number for the function the completion ring is associated
+ * with.
+ */
+ uint16_t cmpl_ring_id;
+ /*
+ * This field is used only when ring_type is a TX ring. This value
+ * indicates what completion ring the TX ring is associated with.
+ */
+ uint16_t queue_id;
+ /*
+ * This field is used only when ring_type is a TX ring. This value
+ * indicates what CoS queue the TX ring is associated with.
+ */
+ uint8_t unused_4;
+ uint8_t unused_5;
+ uint32_t reserved1;
+ /* This field is reserved for the future use. It shall be set to 0. */
+ uint16_t reserved2;
+ /* This field is reserved for the future use. It shall be set to 0. */
+ uint8_t unused_6;
+ uint8_t unused_7;
+ uint32_t reserved3;
+ /* This field is reserved for the future use. It shall be set to 0. */
+ uint32_t stat_ctx_id;
+ /*
+ * This field is used only when ring_type is a TX ring. This input
+ * indicates what statistics context this ring should be associated
+ * with.
+ */
+ uint32_t reserved4;
+ /* This field is reserved for the future use. It shall be set to 0. */
+ uint32_t max_bw;
+ /*
+ * This field is used only when ring_type is a TX ring. Maximum BW
+ * allocated to this TX ring in Mbps. The HWRM will translate this value
+ * into byte counter and time interval used for this ring inside the
+ * device.
+ */
+ uint8_t int_mode;
+ /*
+ * This field is used only when ring_type is a Completion ring. This
+ * value indicates what interrupt mode should be used on this completion
+ * ring. Note: In the legacy interrupt mode, no more than 16 completion
+ * rings are allowed.
+ */
+ /* Legacy INTA */
+ #define HWRM_RING_ALLOC_INPUT_INT_MODE_LEGACY UINT32_C(0x0)
+ /* Reserved */
+ #define HWRM_RING_ALLOC_INPUT_INT_MODE_RSVD UINT32_C(0x1)
+ /* MSI-X */
+ #define HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX UINT32_C(0x2)
+ /* No Interrupt - Polled mode */
+ #define HWRM_RING_ALLOC_INPUT_INT_MODE_POLL UINT32_C(0x3)
+ uint8_t unused_8[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_ring_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t ring_id;
+ /* Physical number of ring allocated. */
+ uint16_t logical_ring_id;
+ /* Logical number of ring allocated. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_ring_free */
+/*
+ * Description: This command is used to free a ring and associated resources.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_ring_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint8_t ring_type;
+ /* Ring Type. */
+ /* Completion Ring (CR) */
+ #define HWRM_RING_FREE_INPUT_RING_TYPE_CMPL UINT32_C(0x0)
+ /* TX Ring (TR) */
+ #define HWRM_RING_FREE_INPUT_RING_TYPE_TX UINT32_C(0x1)
+ /* RX Ring (RR) */
+ #define HWRM_RING_FREE_INPUT_RING_TYPE_RX UINT32_C(0x2)
+ uint8_t unused_0;
+ uint16_t ring_id;
+ /* Physical number of ring allocated. */
+ uint32_t unused_1;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_ring_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_ring_cmpl_ring_qaggint_params */
+/*
+ * Description: This command is used to query aggregation and interrupt related
+ * parameters specified on a given completion ring.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_ring_cmpl_ring_qaggint_params_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t ring_id;
+ /* Physical number of completion ring. */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (32 bytes) */
+
+struct hwrm_ring_cmpl_ring_qaggint_params_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t flags;
+ /*
+ * When this bit is set to '1', interrupt max timer is reset whenever a
+ * completion is received.
+ */
+ #define HWRM_RING_CMPL_RING_QAGGINT_PARAMS_OUTPUT_FLAGS_TIMER_RESET UINT32_C(0x1)
+ /*
+ * When this bit is set to '1', ring idle mode aggregation will be
+ * enabled.
+ */
+ #define HWRM_RING_CMPL_RING_QAGGINT_PARAMS_OUTPUT_FLAGS_RING_IDLE UINT32_C(0x2)
+ uint16_t num_cmpl_dma_aggr;
+ /* Number of completions to aggregate before DMA during the normal mode. */
+ uint16_t num_cmpl_dma_aggr_during_int;
+ /*
+ * Number of completions to aggregate before DMA during the interrupt
+ * mode.
+ */
+ uint16_t cmpl_aggr_dma_tmr;
+ /*
+ * Timer in unit of 80-nsec used to aggregate completions before DMA
+ * during the normal mode (not in interrupt mode).
+ */
+ uint16_t cmpl_aggr_dma_tmr_during_int;
+ /*
+ * Timer in unit of 80-nsec used to aggregate completions before DMA
+ * during the interrupt mode.
+ */
+ uint16_t int_lat_tmr_min;
+ /* Minimum time (in unit of 80-nsec) between two interrupts. */
+ uint16_t int_lat_tmr_max;
+ /*
+ * Maximum wait time (in unit of 80-nsec) spent aggregating completions
+ * before signaling the interrupt after the interrupt is enabled.
+ */
+ uint16_t num_cmpl_aggr_int;
+ /*
+ * Minimum number of completions aggregated before signaling an
+ * interrupt.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_ring_cmpl_ring_cfg_aggint_params */
+/*
+ * Description: This command is used to configure aggregation and interrupt
+ * related parameters specified on a given completion ring.
+ */
+/* Input (40 bytes) */
+
+struct hwrm_ring_cmpl_ring_cfg_aggint_params_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t ring_id;
+ /* Physical number of completion ring. */
+ uint16_t flags;
+ /*
+ * When this bit is set to '1', interrupt latency max timer is reset
+ * whenever a completion is received.
+ */
+ #define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET UINT32_C(0x1)
+ /*
+ * When this bit is set to '1', ring idle mode aggregation will be
+ * enabled.
+ */
+ #define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE UINT32_C(0x2)
+ uint16_t num_cmpl_dma_aggr;
+ /* Number of completions to aggregate before DMA during the normal mode. */
+ uint16_t num_cmpl_dma_aggr_during_int;
+ /*
+ * Number of completions to aggregate before DMA during the interrupt
+ * mode.
+ */
+ uint16_t cmpl_aggr_dma_tmr;
+ /*
+ * Timer in unit of 80-nsec used to aggregate completions before DMA
+ * during the normal mode (not in interrupt mode).
+ */
+ uint16_t cmpl_aggr_dma_tmr_during_int;
+ /*
+ * Timer in unit of 80-nsec used to aggregate completions before DMA
+ * during the interrupt mode.
+ */
+ uint16_t int_lat_tmr_min;
+ /* Minimum time (in unit of 80-nsec) between two interrupts. */
+ uint16_t int_lat_tmr_max;
+ /*
+ * Maximum wait time (in unit of 80-nsec) spent aggregating cmpls before
+ * signaling the interrupt after the interrupt is enabled.
+ */
+ uint16_t num_cmpl_aggr_int;
+ /*
+ * Minimum number of completions aggregated before signaling an
+ * interrupt.
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_ring_cmpl_ring_cfg_aggint_params_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_ring_reset */
+/*
+ * Description: This command is used to reset a given ring. When an RX ring is
+ * being reset, the HWRM shall perform TPA flush on all VNICs associated with
+ * the RX ring that is being reset.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_ring_reset_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint8_t ring_type;
+ /* Ring Type. */
+ /* Completion Ring (CR) */
+ #define HWRM_RING_RESET_INPUT_RING_TYPE_CMPL UINT32_C(0x0)
+ /* TX Ring (TR) */
+ #define HWRM_RING_RESET_INPUT_RING_TYPE_TX UINT32_C(0x1)
+ /* RX Ring (RR) */
+ #define HWRM_RING_RESET_INPUT_RING_TYPE_RX UINT32_C(0x2)
+ uint8_t unused_0;
+ uint16_t ring_id;
+ /* Physical number of the ring. */
+ uint32_t unused_1;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_ring_reset_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_ring_grp_alloc */
+/*
+ * Description: This API allocates and does basic preparation for a ring group.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_ring_grp_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t cr;
+ /* This value identifies the CR associated with the ring group. */
+ uint16_t rr;
+ /* This value identifies the main RR associated with the ring group. */
+ uint16_t ar;
+ /*
+ * This value identifies the aggregation RR associated with the ring
+ * group. If this value is 0xFF... (All Fs), then no Aggregation ring
+ * will be set.
+ */
+ uint16_t sc;
+ /*
+ * This value identifies the statistics context associated with the ring
+ * group.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_ring_grp_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t ring_group_id;
+ /*
+ * This is the ring group ID value. Use this value to program the
+ * default ring group for the VNIC or as table entries in an RSS/COS
+ * context.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_ring_grp_free */
+/*
+ * Description: This API frees a ring group and associated resources. # If a
+ * ring in the ring group is reset or free, then the associated rings in the
+ * ring group shall also be reset/free using hwrm_ring_free. # A function driver
+ * shall always use hwrm_ring_grp_free after freeing all rings in a group. # As
+ * a part of executing this command, the HWRM shall reset all associated ring
+ * group resources.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_ring_grp_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t ring_group_id;
+ /* This is the ring group ID value. */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_ring_grp_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_l2_filter_alloc */
+/*
+ * Description: An L2 filter is a filter resource that is used to identify a
+ * vnic or ring for a packet based on layer 2 fields. Layer 2 fields for
+ * encapsulated packets include both outer L2 header and/or inner l2 header of
+ * encapsulated packet. The L2 filter resource covers the following OS specific
+ * L2 filters. Linux/FreeBSD (per function): # Broadcast enable/disable # List
+ * of individual multicast filters # All multicast enable/disable filter #
+ * Unicast filters # Promiscuous mode VMware: # Broadcast enable/disable (per
+ * physical function) # All multicast enable/disable (per function) # Unicast
+ * filters per ring or vnic # Promiscuous mode per PF Windows: # Broadcast
+ * enable/disable (per physical function) # List of individual multicast filters
+ * (Driver needs to advertise the maximum number of filters supported) # All
+ * multicast enable/disable per physical function # Unicast filters per vnic #
+ * Promiscuous mode per PF Implementation notes on the use of VNIC in this
+ * command: # By default, these filters belong to default vnic for the function.
+ * # Once these filters are set up, only destination VNIC can be modified. # If
+ * the destination VNIC is not specified in this command, then the HWRM shall
+ * only create an l2 context id. HWRM Implementation notes for multicast
+ * filters: # The hwrm_filter_alloc command can be used to set up multicast
+ * filters (perfect match or partial match). Each individual function driver can
+ * set up multicast filters independently. # The HWRM needs to keep track of
+ * multicast filters set up by function drivers and maintain multicast group
+ * replication records to enable a subset of functions to receive traffic for a
+ * specific multicast address. # When a specific multicast filter cannot be set,
+ * the HWRM shall return an error. In this error case, the driver should fall
+ * back to using one general filter (rather than specific) for all multicast
+ * traffic. # When the SR-IOV is enabled, the HWRM needs to additionally track
+ * source knockout per multicast group record. Examples of setting unicast
+ * filters: For a unicast MAC based filter, one can use a combination of the
+ * fields and masks provided in this command to set up the filter. Below are
+ * some examples: # MAC + no VLAN filter: This filter is used to identify
+ * traffic that does not contain any VLAN tags and matches destination (or
+ * source) MAC address. This filter can be set up by setting only l2_addr field
+ * to be a valid field. All other fields are not valid. The following value is
+ * set for l2_addr. l2_addr = MAC # MAC + Any VLAN filter: This filter is used
+ * to identify traffic that carries single VLAN tag and matches (destination or
+ * source) MAC address. This filter can be set up by setting only l2_addr and
+ * l2_ovlan_mask fields to be valid fields. All other fields are not valid. The
+ * following values are set for those two valid fields. l2_addr = MAC,
+ * l2_ovlan_mask = 0xFFFF # MAC + no VLAN or VLAN ID=0: This filter is used to
+ * identify untagged traffic that does not contain any VLAN tags or a VLAN tag
+ * with VLAN ID = 0 and matches destination (or source) MAC address. This filter
+ * can be set up by setting only l2_addr and l2_ovlan fields to be valid fields.
+ * All other fields are not valid. The following value are set for l2_addr and
+ * l2_ovlan. l2_addr = MAC, l2_ovlan = 0x0 # MAC + no VLAN or any VLAN: This
+ * filter is used to identify traffic that contains zero or 1 VLAN tag and
+ * matches destination (or source) MAC address. This filter can be set up by
+ * setting only l2_addr, l2_ovlan, and l2_mask fields to be valid fields. All
+ * other fields are not valid. The following value are set for l2_addr,
+ * l2_ovlan, and l2_mask fields. l2_addr = MAC, l2_ovlan = 0x0, l2_ovlan_mask =
+ * 0xFFFF # MAC + VLAN ID filter: This filter can be set up by setting only
+ * l2_addr, l2_ovlan, and l2_ovlan_mask fields to be valid fields. All other
+ * fields are not valid. The following values are set for those three valid
+ * fields. l2_addr = MAC, l2_ovlan = VLAN ID, l2_ovlan_mask = 0xF000
+ */
+/* Input (96 bytes) */
+
+struct hwrm_cfa_l2_filter_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_TX (UINT32_C(0x0) << 0)
+ /* rx path */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX (UINT32_C(0x1) << 0)
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_LAST HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX
+ /*
+ * Setting of this flag indicates the applicability to the loopback
+ * path.
+ */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_LOOPBACK UINT32_C(0x2)
+ /*
+ * Setting of this flag indicates drop action. If this flag is not set,
+ * then it should be considered accept action.
+ */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_DROP UINT32_C(0x4)
+ /*
+ * If this flag is set, all t_l2_* fields are invalid and they should
+ * not be specified. If this flag is set, then l2_* fields refer to
+ * fields of outermost L2 header.
+ */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST UINT32_C(0x8)
+ uint32_t enables;
+ /* This bit must be '1' for the l2_addr field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR UINT32_C(0x1)
+ /* This bit must be '1' for the l2_addr_mask field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK UINT32_C(0x2)
+ /* This bit must be '1' for the l2_ovlan field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_OVLAN UINT32_C(0x4)
+ /* This bit must be '1' for the l2_ovlan_mask field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_OVLAN_MASK UINT32_C(0x8)
+ /* This bit must be '1' for the l2_ivlan field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN UINT32_C(0x10)
+ /* This bit must be '1' for the l2_ivlan_mask field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN_MASK UINT32_C(0x20)
+ /* This bit must be '1' for the t_l2_addr field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_ADDR UINT32_C(0x40)
+ /* This bit must be '1' for the t_l2_addr_mask field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_ADDR_MASK UINT32_C(0x80)
+ /* This bit must be '1' for the t_l2_ovlan field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_OVLAN UINT32_C(0x100)
+ /* This bit must be '1' for the t_l2_ovlan_mask field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_OVLAN_MASK UINT32_C(0x200)
+ /* This bit must be '1' for the t_l2_ivlan field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_IVLAN UINT32_C(0x400)
+ /* This bit must be '1' for the t_l2_ivlan_mask field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_IVLAN_MASK UINT32_C(0x800)
+ /* This bit must be '1' for the src_type field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_SRC_TYPE UINT32_C(0x1000)
+ /* This bit must be '1' for the src_id field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_SRC_ID UINT32_C(0x2000)
+ /* This bit must be '1' for the tunnel_type field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_TUNNEL_TYPE UINT32_C(0x4000)
+ /* This bit must be '1' for the dst_id field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID UINT32_C(0x8000)
+ /* This bit must be '1' for the mirror_vnic_id field to be configured. */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_MIRROR_VNIC_ID UINT32_C(0x10000)
+ uint8_t l2_addr[6];
+ /*
+ * This value sets the match value for the L2 MAC address. Destination
+ * MAC address for RX path. Source MAC address for TX path.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t l2_addr_mask[6];
+ /*
+ * This value sets the mask value for the L2 address. A value of 0 will
+ * mask the corresponding bit from compare.
+ */
+ uint16_t l2_ovlan;
+ /* This value sets VLAN ID value for outer VLAN. */
+ uint16_t l2_ovlan_mask;
+ /*
+ * This value sets the mask value for the ovlan id. A value of 0 will
+ * mask the corresponding bit from compare.
+ */
+ uint16_t l2_ivlan;
+ /* This value sets VLAN ID value for inner VLAN. */
+ uint16_t l2_ivlan_mask;
+ /*
+ * This value sets the mask value for the ivlan id. A value of 0 will
+ * mask the corresponding bit from compare.
+ */
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t t_l2_addr[6];
+ /*
+ * This value sets the match value for the tunnel L2 MAC address.
+ * Destination MAC address for RX path. Source MAC address for TX path.
+ */
+ uint8_t unused_4;
+ uint8_t unused_5;
+ uint8_t t_l2_addr_mask[6];
+ /*
+ * This value sets the mask value for the tunnel L2 address. A value of
+ * 0 will mask the corresponding bit from compare.
+ */
+ uint16_t t_l2_ovlan;
+ /* This value sets VLAN ID value for tunnel outer VLAN. */
+ uint16_t t_l2_ovlan_mask;
+ /*
+ * This value sets the mask value for the tunnel ovlan id. A value of 0
+ * will mask the corresponding bit from compare.
+ */
+ uint16_t t_l2_ivlan;
+ /* This value sets VLAN ID value for tunnel inner VLAN. */
+ uint16_t t_l2_ivlan_mask;
+ /*
+ * This value sets the mask value for the tunnel ivlan id. A value of 0
+ * will mask the corresponding bit from compare.
+ */
+ uint8_t src_type;
+ /* This value identifies the type of source of the packet. */
+ /* Network port */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_NPORT UINT32_C(0x0)
+ /* Physical function */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_PF UINT32_C(0x1)
+ /* Virtual function */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_VF UINT32_C(0x2)
+ /* Virtual NIC of a function */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_VNIC UINT32_C(0x3)
+ /* Embedded processor for CFA management */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_KONG UINT32_C(0x4)
+ /* Embedded processor for OOB management */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_APE UINT32_C(0x5)
+ /* Embedded processor for RoCE */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_BONO UINT32_C(0x6)
+ /* Embedded processor for network proxy functions */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_TANG UINT32_C(0x7)
+ uint8_t unused_6;
+ uint32_t src_id;
+ /*
+ * This value is the id of the source. For a network port, it represents
+ * port_id. For a physical function, it represents fid. For a virtual
+ * function, it represents vf_id. For a vnic, it represents vnic_id. For
+ * embedded processors, this id is not valid. Notes: 1. The function ID
+ * is implied if it src_id is not provided for a src_type that is either
+ */
+ uint8_t tunnel_type;
+ /* Tunnel Type. */
+ /* Non-tunnel */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NONTUNNEL UINT32_C(0x0)
+ /* Virtual eXtensible Local Area Network (VXLAN) */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1)
+ /* Network Virtualization Generic Routing Encapsulation (NVGRE) */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NVGRE UINT32_C(0x2)
+ /* Generic Routing Encapsulation (GRE) inside Ethernet payload */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_L2GRE UINT32_C(0x3)
+ /* IP in IP */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPIP UINT32_C(0x4)
+ /* Generic Network Virtualization Encapsulation (Geneve) */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5)
+ /* Multi-Protocol Lable Switching (MPLS) */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_MPLS UINT32_C(0x6)
+ /* Stateless Transport Tunnel (STT) */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_STT UINT32_C(0x7)
+ /* Generic Routing Encapsulation (GRE) inside IP datagram payload */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPGRE UINT32_C(0x8)
+ /* Any tunneled traffic */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_ANYTUNNEL UINT32_C(0xff)
+ uint8_t unused_7;
+ uint16_t dst_id;
+ /*
+ * If set, this value shall represent the Logical VNIC ID of the
+ * destination VNIC for the RX path and network port id of the
+ * destination port for the TX path.
+ */
+ uint16_t mirror_vnic_id;
+ /* Logical VNIC ID of the VNIC where traffic is mirrored. */
+ uint8_t pri_hint;
+ /*
+ * This hint is provided to help in placing the filter in the filter
+ * table.
+ */
+ /* No preference */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_NO_PREFER UINT32_C(0x0)
+ /* Above the given filter */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_ABOVE_FILTER UINT32_C(0x1)
+ /* Below the given filter */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_BELOW_FILTER UINT32_C(0x2)
+ /* As high as possible */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_MAX UINT32_C(0x3)
+ /* As low as possible */
+ #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_MIN UINT32_C(0x4)
+ uint8_t unused_8;
+ uint32_t unused_9;
+ uint64_t l2_filter_id_hint;
+ /*
+ * This is the ID of the filter that goes along with the pri_hint. This
+ * field is valid only for the following values. 1 - Above the given
+ * filter 2 - Below the given filter
+ */
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_cfa_l2_filter_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint64_t l2_filter_id;
+ /*
+ * This value identifies a set of CFA data structures used for an L2
+ * context.
+ */
+ uint32_t flow_id;
+ /*
+ * This is the ID of the flow associated with this filter. This value
+ * shall be used to match and associate the flow identifier returned in
+ * completion records. A value of 0xFFFFFFFF shall indicate no flow id.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_l2_filter_free */
+/*
+ * Description: Free a L2 filter. The HWRM shall free all associated filter
+ * resources with the L2 filter.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_cfa_l2_filter_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t l2_filter_id;
+ /*
+ * This value identifies a set of CFA data structures used for an L2
+ * context.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_cfa_l2_filter_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_l2_filter_cfg */
+/* Description: Change the configuration of an existing L2 filter */
+/* Input (40 bytes) */
+
+struct hwrm_cfa_l2_filter_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_TX (UINT32_C(0x0) << 0)
+ /* rx path */
+ #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_RX (UINT32_C(0x1) << 0)
+ #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_LAST HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_RX
+ /*
+ * Setting of this flag indicates drop action. If this flag is not set,
+ * then it should be considered accept action.
+ */
+ #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_DROP UINT32_C(0x2)
+ uint32_t enables;
+ /* This bit must be '1' for the dst_id field to be configured. */
+ #define HWRM_CFA_L2_FILTER_CFG_INPUT_ENABLES_DST_ID UINT32_C(0x1)
+ /*
+ * This bit must be '1' for the new_mirror_vnic_id field to be
+ * configured.
+ */
+ #define HWRM_CFA_L2_FILTER_CFG_INPUT_ENABLES_NEW_MIRROR_VNIC_ID UINT32_C(0x2)
+ uint64_t l2_filter_id;
+ /*
+ * This value identifies a set of CFA data structures used for an L2
+ * context.
+ */
+ uint32_t dst_id;
+ /*
+ * If set, this value shall represent the Logical VNIC ID of the
+ * destination VNIC for the RX path and network port id of the
+ * destination port for the TX path.
+ */
+ uint32_t new_mirror_vnic_id;
+ /* New Logical VNIC ID of the VNIC where traffic is mirrored. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_cfa_l2_filter_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_l2_set_rx_mask */
+/* Description: This command will set rx mask of the function. */
+/* Input (56 bytes) */
+
+struct hwrm_cfa_l2_set_rx_mask_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t vnic_id;
+ /* VNIC ID */
+ uint32_t mask;
+ /* Reserved for future use. */
+ #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_RESERVED UINT32_C(0x1)
+ /*
+ * When this bit is '1', the function is requested to accept multi-cast
+ * packets specified by the multicast addr table.
+ */
+ #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_MCAST UINT32_C(0x2)
+ /*
+ * When this bit is '1', the function is requested to accept all multi-
+ * cast packets.
+ */
+ #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST UINT32_C(0x4)
+ /*
+ * When this bit is '1', the function is requested to accept broadcast
+ * packets.
+ */
+ #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST UINT32_C(0x8)
+ /*
+ * When this bit is '1', the function is requested to be put in the
+ * promiscuous mode. The HWRM should accept any function to set up
+ * promiscuous mode. The HWRM shall follow the semantics below for the
+ * promiscuous mode support. # When partitioning is not enabled on a
+ * port (i.e. single PF on the port), then the PF shall be allowed to be
+ * in the promiscuous mode. When the PF is in the promiscuous mode, then
+ * it shall receive all host bound traffic on that port. # When
+ * partitioning is enabled on a port (i.e. multiple PFs per port) and a
+ * PF on that port is in the promiscuous mode, then the PF receives all
+ * traffic within that partition as identified by a unique identifier
+ * for the PF (e.g. S-Tag). If a unique outer VLAN for the PF is
+ * specified, then the setting of promiscuous mode on that PF shall
+ * result in the PF receiving all host bound traffic with matching outer
+ * VLAN. # A VF shall can be set in the promiscuous mode. In the
+ * promiscuous mode, the VF does not receive any traffic unless a unique
+ * outer VLAN for the VF is specified. If a unique outer VLAN for the VF
+ * is specified, then the setting of promiscuous mode on that VF shall
+ * result in the VF receiving all host bound traffic with the matching
+ * outer VLAN. # The HWRM shall allow the setting of promiscuous mode on
+ * a function independently from the promiscuous mode settings on other
+ * functions.
+ */
+ #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS UINT32_C(0x10)
+ /*
+ * If this flag is set, the corresponding RX filters shall be set up to
+ * cover multicast/broadcast filters for the outermost Layer 2
+ * destination MAC address field.
+ */
+ #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_OUTERMOST UINT32_C(0x20)
+ /*
+ * If this flag is set, the corresponding RX filters shall be set up to
+ * cover multicast/broadcast filters for the VLAN-tagged packets that
+ * match the TPID and VID fields of VLAN tags in the VLAN tag table
+ * specified in this command.
+ */
+ #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY UINT32_C(0x40)
+ /*
+ * If this flag is set, the corresponding RX filters shall be set up to
+ * cover multicast/broadcast filters for non-VLAN tagged packets and
+ * VLAN-tagged packets that match the TPID and VID fields of VLAN tags
+ * in the VLAN tag table specified in this command.
+ */
+ #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN UINT32_C(0x80)
+ /*
+ * If this flag is set, the corresponding RX filters shall be set up to
+ * cover multicast/broadcast filters for non-VLAN tagged packets and
+ * VLAN-tagged packets matching any VLAN tag. If this flag is set, then
+ * the HWRM shall ignore VLAN tags specified in vlan_tag_tbl. If none of
+ * vlanonly, vlan_nonvlan, and anyvlan_nonvlan flags is set, then the
+ * HWRM shall ignore VLAN tags specified in vlan_tag_tbl. The HWRM
+ * client shall set at most one flag out of vlanonly, vlan_nonvlan, and
+ * anyvlan_nonvlan.
+ */
+ #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN UINT32_C(0x100)
+ uint64_t mc_tbl_addr;
+ /* This is the address for mcast address tbl. */
+ uint32_t num_mc_entries;
+ /*
+ * This value indicates how many entries in mc_tbl are valid. Each entry
+ * is 6 bytes.
+ */
+ uint32_t unused_0;
+ uint64_t vlan_tag_tbl_addr;
+ /*
+ * This is the address for VLAN tag table. Each VLAN entry in the table
+ * is 4 bytes of a VLAN tag including TPID, PCP, DEI, and VID fields in
+ * network byte order.
+ */
+ uint32_t num_vlan_tags;
+ /*
+ * This value indicates how many entries in vlan_tag_tbl are valid. Each
+ * entry is 4 bytes.
+ */
+ uint32_t unused_1;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_cfa_l2_set_rx_mask_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_tunnel_filter_alloc */
+/*
+ * Description: This is a tunnel filter that uses fields from tunnel header in
+ * addition to l2 context. The tunnel filter applies to receive side only. The
+ * l2_* fields in this command represent fields of inner L2 header. They are
+ * optional to be specified. It allows l2_filter_id to be created with outer L2
+ * header fields that can be shared with multiple tunnel filters specified as
+ * combinations of inner L2 header fields, tunnel type, and VNI.
+ */
+/* Input (88 bytes) */
+
+struct hwrm_cfa_tunnel_filter_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Setting of this flag indicates the applicability to the loopback
+ * path.
+ */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_FLAGS_LOOPBACK UINT32_C(0x1)
+ uint32_t enables;
+ /* This bit must be '1' for the l2_filter_id field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_L2_FILTER_ID UINT32_C(0x1)
+ /* This bit must be '1' for the l2_addr field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR UINT32_C(0x2)
+ /* This bit must be '1' for the l2_ivlan field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN UINT32_C(0x4)
+ /* This bit must be '1' for the l3_addr field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_L3_ADDR UINT32_C(0x8)
+ /* This bit must be '1' for the l3_addr_type field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_L3_ADDR_TYPE UINT32_C(0x10)
+ /* This bit must be '1' for the t_l3_addr_type field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_T_L3_ADDR_TYPE UINT32_C(0x20)
+ /* This bit must be '1' for the t_l3_addr field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_T_L3_ADDR UINT32_C(0x40)
+ /* This bit must be '1' for the tunnel_type field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_TUNNEL_TYPE UINT32_C(0x80)
+ /* This bit must be '1' for the vni field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_VNI UINT32_C(0x100)
+ /* This bit must be '1' for the dst_vnic_id field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_DST_VNIC_ID UINT32_C(0x200)
+ /* This bit must be '1' for the mirror_vnic_id field to be configured. */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_MIRROR_VNIC_ID UINT32_C(0x400)
+ uint64_t l2_filter_id;
+ /*
+ * This value identifies a set of CFA data structures used for an L2
+ * context.
+ */
+ uint8_t l2_addr[6];
+ /*
+ * This value sets the match value for the inner L2 MAC address.
+ * Destination MAC address for RX path. Source MAC address for TX path.
+ */
+ uint16_t l2_ivlan;
+ /*
+ * This value sets VLAN ID value for inner VLAN. Only 12-bits of VLAN ID
+ * are used in setting the filter.
+ */
+ uint32_t l3_addr[4];
+ /*
+ * The value of inner destination IP address to be used in filtering.
+ * For IPv4, first four bytes represent the IP address.
+ */
+ uint32_t t_l3_addr[4];
+ /*
+ * The value of tunnel destination IP address to be used in filtering.
+ * For IPv4, first four bytes represent the IP address.
+ */
+ uint8_t l3_addr_type;
+ /*
+ * This value indicates the type of inner IP address. 4 - IPv4 6 - IPv6
+ * All others are invalid.
+ */
+ uint8_t t_l3_addr_type;
+ /*
+ * This value indicates the type of tunnel IP address. 4 - IPv4 6 - IPv6
+ * All others are invalid.
+ */
+ uint8_t tunnel_type;
+ /* Tunnel Type. */
+ /* Non-tunnel */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NONTUNNEL UINT32_C(0x0)
+ /* Virtual eXtensible Local Area Network (VXLAN) */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1)
+ /* Network Virtualization Generic Routing Encapsulation (NVGRE) */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NVGRE UINT32_C(0x2)
+ /* Generic Routing Encapsulation (GRE) inside Ethernet payload */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_L2GRE UINT32_C(0x3)
+ /* IP in IP */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPIP UINT32_C(0x4)
+ /* Generic Network Virtualization Encapsulation (Geneve) */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5)
+ /* Multi-Protocol Lable Switching (MPLS) */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_MPLS UINT32_C(0x6)
+ /* Stateless Transport Tunnel (STT) */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_STT UINT32_C(0x7)
+ /* Generic Routing Encapsulation (GRE) inside IP datagram payload */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPGRE UINT32_C(0x8)
+ /* Any tunneled traffic */
+ #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_ANYTUNNEL UINT32_C(0xff)
+ uint8_t unused_0;
+ uint32_t vni;
+ /*
+ * Virtual Network Identifier (VNI). Only valid with tunnel_types VXLAN,
+ * NVGRE, and Geneve. Only lower 24-bits of VNI field are used in
+ * setting up the filter.
+ */
+ uint32_t dst_vnic_id;
+ /* Logical VNIC ID of the destination VNIC. */
+ uint32_t mirror_vnic_id;
+ /* Logical VNIC ID of the VNIC where traffic is mirrored. */
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_cfa_tunnel_filter_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint64_t tunnel_filter_id;
+ /* This value is an opaque id into CFA data structures. */
+ uint32_t flow_id;
+ /*
+ * This is the ID of the flow associated with this filter. This value
+ * shall be used to match and associate the flow identifier returned in
+ * completion records. A value of 0xFFFFFFFF shall indicate no flow id.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_tunnel_filter_free */
+/* Description: Free a tunnel filter */
+/* Input (24 bytes) */
+
+struct hwrm_cfa_tunnel_filter_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t tunnel_filter_id;
+ /* This value is an opaque id into CFA data structures. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_cfa_tunnel_filter_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_encap_record_alloc */
+/*
+ * Description: This command is used to create an encapsulation record. The
+ * source MAC address and source IP address specified for the source property
+ * checks shall be used in the encapsulation where applicable.
+ */
+/* Input (32 bytes) */
+
+struct hwrm_cfa_encap_record_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Setting of this flag indicates the applicability to the loopback
+ * path.
+ */
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_FLAGS_LOOPBACK UINT32_C(0x1)
+ uint8_t encap_type;
+ /* Encapsulation Type. */
+ /* Virtual eXtensible Local Area Network (VXLAN) */
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_VXLAN UINT32_C(0x1)
+ /* Network Virtualization Generic Routing Encapsulation (NVGRE) */
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_NVGRE UINT32_C(0x2)
+ /* Generic Routing Encapsulation (GRE) after inside Ethernet payload */
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_L2GRE UINT32_C(0x3)
+ /* IP in IP */
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_IPIP UINT32_C(0x4)
+ /* Generic Network Virtualization Encapsulation (Geneve) */
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_GENEVE UINT32_C(0x5)
+ /* Multi-Protocol Lable Switching (MPLS) */
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_MPLS UINT32_C(0x6)
+ /* VLAN */
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_VLAN UINT32_C(0x7)
+ /* Generic Routing Encapsulation (GRE) inside IP datagram payload */
+ #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_IPGRE UINT32_C(0x8)
+ uint8_t unused_0;
+ uint16_t unused_1;
+ uint32_t encap_data[16];
+ /* This value is encap data used for the given encap type. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_cfa_encap_record_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t encap_record_id;
+ /* This value is an opaque id into CFA data structures. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_encap_record_free */
+/* Description: Free an encap record */
+/* Input (24 bytes) */
+
+struct hwrm_cfa_encap_record_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t encap_record_id;
+ /* This value is an opaque id into CFA data structures. */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_cfa_encap_record_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_ntuple_filter_alloc */
+/*
+ * Description: This is a ntuple filter that uses fields from L4/L3 header and
+ * optionally fields from L2. The ntuple filters apply to receive traffic only.
+ * All L2/L3/L4 header fields are specified in network byte order. These filters
+ * can be used for Receive Flow Steering (RFS). # For ethertype value, only
+ * 0x0800 (IPv4) and 0x86dd (IPv6) shall be supported for ntuple filters. # If a
+ * field specified in this command is not enabled as a valid field, then that
+ * field shall not be used in matching packet header fields against this filter.
+ */
+/* Input (128 bytes) */
+
+struct hwrm_cfa_ntuple_filter_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Setting of this flag indicates the applicability to the loopback
+ * path.
+ */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_FLAGS_LOOPBACK UINT32_C(0x1)
+ /*
+ * Setting of this flag indicates drop action. If this flag is not set,
+ * then it should be considered accept action.
+ */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_FLAGS_DROP UINT32_C(0x2)
+ uint32_t enables;
+ /* This bit must be '1' for the l2_filter_id field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_L2_FILTER_ID UINT32_C(0x1)
+ /* This bit must be '1' for the ethertype field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_ETHERTYPE UINT32_C(0x2)
+ /* This bit must be '1' for the tunnel_type field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_TUNNEL_TYPE UINT32_C(0x4)
+ /* This bit must be '1' for the src_macaddr field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_SRC_MACADDR UINT32_C(0x8)
+ /* This bit must be '1' for the ipaddr_type field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_IPADDR_TYPE UINT32_C(0x10)
+ /* This bit must be '1' for the src_ipaddr field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_SRC_IPADDR UINT32_C(0x20)
+ /* This bit must be '1' for the src_ipaddr_mask field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_SRC_IPADDR_MASK UINT32_C(0x40)
+ /* This bit must be '1' for the dst_ipaddr field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_IPADDR UINT32_C(0x80)
+ /* This bit must be '1' for the dst_ipaddr_mask field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_IPADDR_MASK UINT32_C(0x100)
+ /* This bit must be '1' for the ip_protocol field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_IP_PROTOCOL UINT32_C(0x200)
+ /* This bit must be '1' for the src_port field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_SRC_PORT UINT32_C(0x400)
+ /* This bit must be '1' for the src_port_mask field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_SRC_PORT_MASK UINT32_C(0x800)
+ /* This bit must be '1' for the dst_port field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_PORT UINT32_C(0x1000)
+ /* This bit must be '1' for the dst_port_mask field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_PORT_MASK UINT32_C(0x2000)
+ /* This bit must be '1' for the pri_hint field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_PRI_HINT UINT32_C(0x4000)
+ /* This bit must be '1' for the ntuple_filter_id field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_NTUPLE_FILTER_ID UINT32_C(0x8000)
+ /* This bit must be '1' for the dst_id field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_ID UINT32_C(0x10000)
+ /* This bit must be '1' for the mirror_vnic_id field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_MIRROR_VNIC_ID UINT32_C(0x20000)
+ /* This bit must be '1' for the dst_macaddr field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_MACADDR UINT32_C(0x40000)
+ uint64_t l2_filter_id;
+ /*
+ * This value identifies a set of CFA data structures used for an L2
+ * context.
+ */
+ uint8_t src_macaddr[6];
+ /* This value indicates the source MAC address in the Ethernet header. */
+ uint16_t ethertype; /* big endian */
+ /* This value indicates the ethertype in the Ethernet header. */
+ uint8_t ip_addr_type;
+ /*
+ * This value indicates the type of IP address. 4 - IPv4 6 - IPv6 All
+ * others are invalid.
+ */
+ /* invalid */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_UNKNOWN UINT32_C(0x0)
+ /* IPv4 */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV4 UINT32_C(0x4)
+ /* IPv6 */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 UINT32_C(0x6)
+ uint8_t ip_protocol;
+ /*
+ * The value of protocol filed in IP header. Applies to UDP and TCP
+ * traffic. 6 - UDP 17 - TCP
+ */
+ /* invalid */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_PROTOCOL_UNKNOWN UINT32_C(0x0)
+ /* UDP */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_PROTOCOL_UDP UINT32_C(0x6)
+ /* TCP */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_PROTOCOL_TCP UINT32_C(0x11)
+ uint16_t dst_id;
+ /*
+ * If set, this value shall represent the Logical VNIC ID of the
+ * destination VNIC for the RX path and network port id of the
+ * destination port for the TX path.
+ */
+ uint16_t mirror_vnic_id;
+ /* Logical VNIC ID of the VNIC where traffic is mirrored. */
+ uint8_t tunnel_type;
+ /*
+ * This value indicates the tunnel type for this filter. If this field
+ * is not specified, then the filter shall apply to both non-tunneled
+ * and tunneled packets. If this field conflicts with the tunnel_type
+ * specified in the l2_filter_id, then the HWRM shall return an error
+ * for this command.
+ */
+ /* Non-tunnel */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NONTUNNEL UINT32_C(0x0)
+ /* Virtual eXtensible Local Area Network (VXLAN) */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1)
+ /* Network Virtualization Generic Routing Encapsulation (NVGRE) */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NVGRE UINT32_C(0x2)
+ /* Generic Routing Encapsulation (GRE) inside Ethernet payload */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_L2GRE UINT32_C(0x3)
+ /* IP in IP */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPIP UINT32_C(0x4)
+ /* Generic Network Virtualization Encapsulation (Geneve) */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5)
+ /* Multi-Protocol Lable Switching (MPLS) */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_MPLS UINT32_C(0x6)
+ /* Stateless Transport Tunnel (STT) */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_STT UINT32_C(0x7)
+ /* Generic Routing Encapsulation (GRE) inside IP datagram payload */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPGRE UINT32_C(0x8)
+ /* Any tunneled traffic */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_ANYTUNNEL UINT32_C(0xff)
+ uint8_t pri_hint;
+ /*
+ * This hint is provided to help in placing the filter in the filter
+ * table.
+ */
+ /* No preference */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_PRI_HINT_NO_PREFER UINT32_C(0x0)
+ /* Above the given filter */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_PRI_HINT_ABOVE UINT32_C(0x1)
+ /* Below the given filter */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_PRI_HINT_BELOW UINT32_C(0x2)
+ /* As high as possible */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_PRI_HINT_HIGHEST UINT32_C(0x3)
+ /* As low as possible */
+ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_PRI_HINT_LOWEST UINT32_C(0x4)
+ uint32_t src_ipaddr[4]; /* big endian */
+ /*
+ * The value of source IP address to be used in filtering. For IPv4,
+ * first four bytes represent the IP address.
+ */
+ uint32_t src_ipaddr_mask[4]; /* big endian */
+ /*
+ * The value of source IP address mask to be used in filtering. For
+ * IPv4, first four bytes represent the IP address mask.
+ */
+ uint32_t dst_ipaddr[4]; /* big endian */
+ /*
+ * The value of destination IP address to be used in filtering. For
+ * IPv4, first four bytes represent the IP address.
+ */
+ uint32_t dst_ipaddr_mask[4]; /* big endian */
+ /*
+ * The value of destination IP address mask to be used in filtering. For
+ * IPv4, first four bytes represent the IP address mask.
+ */
+ uint16_t src_port; /* big endian */
+ /*
+ * The value of source port to be used in filtering. Applies to UDP and
+ * TCP traffic.
+ */
+ uint16_t src_port_mask; /* big endian */
+ /*
+ * The value of source port mask to be used in filtering. Applies to UDP
+ * and TCP traffic.
+ */
+ uint16_t dst_port; /* big endian */
+ /*
+ * The value of destination port to be used in filtering. Applies to UDP
+ * and TCP traffic.
+ */
+ uint16_t dst_port_mask; /* big endian */
+ /*
+ * The value of destination port mask to be used in filtering. Applies
+ * to UDP and TCP traffic.
+ */
+ uint64_t ntuple_filter_id_hint;
+ /* This is the ID of the filter that goes along with the pri_hint. */
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_cfa_ntuple_filter_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint64_t ntuple_filter_id;
+ /* This value is an opaque id into CFA data structures. */
+ uint32_t flow_id;
+ /*
+ * This is the ID of the flow associated with this filter. This value
+ * shall be used to match and associate the flow identifier returned in
+ * completion records. A value of 0xFFFFFFFF shall indicate no flow id.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_ntuple_filter_free */
+/* Description: Free an ntuple filter */
+/* Input (24 bytes) */
+
+struct hwrm_cfa_ntuple_filter_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t ntuple_filter_id;
+ /* This value is an opaque id into CFA data structures. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_cfa_ntuple_filter_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_ntuple_filter_cfg */
+/* Description: Configure an ntuple filter with new destination VNIC */
+/* Input (40 bytes) */
+
+struct hwrm_cfa_ntuple_filter_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the new_dst_id field to be configured. */
+ #define HWRM_CFA_NTUPLE_FILTER_CFG_INPUT_ENABLES_NEW_DST_ID UINT32_C(0x1)
+ /*
+ * This bit must be '1' for the new_mirror_vnic_id field to be
+ * configured.
+ */
+ #define HWRM_CFA_NTUPLE_FILTER_CFG_INPUT_ENABLES_NEW_MIRROR_VNIC_ID UINT32_C(0x2)
+ uint32_t unused_0;
+ uint64_t ntuple_filter_id;
+ /* This value is an opaque id into CFA data structures. */
+ uint32_t new_dst_id;
+ /*
+ * If set, this value shall represent the new Logical VNIC ID of the
+ * destination VNIC for the RX path and new network port id of the
+ * destination port for the TX path.
+ */
+ uint32_t new_mirror_vnic_id;
+ /* New Logical VNIC ID of the VNIC where traffic is mirrored. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_cfa_ntuple_filter_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_em_flow_alloc */
+/*
+ * Description: This is a generic Exact Match (EM) flow that uses fields from
+ * L4/L3/L2 headers. The EM flows apply to transmit and receive traffic. All
+ * L2/L3/L4 header fields are specified in network byte order. For each EM flow,
+ * there is an associated set of actions specified. For tunneled packets, all
+ * L2/L3/L4 fields specified are fields of inner headers unless otherwise
+ * specified. # If a field specified in this command is not enabled as a valid
+ * field, then that field shall not be used in matching packet header fields
+ * against this EM flow entry.
+ */
+/* Input (112 bytes) */
+
+struct hwrm_cfa_em_flow_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource. This
+ * enumeration is used for resources that are similar for both TX and RX
+ * paths of the chip.
+ */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH UINT32_C(0x1)
+ /* tx path */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_TX (UINT32_C(0x0) << 0)
+ /* rx path */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_RX (UINT32_C(0x1) << 0)
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_LAST HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_RX
+ /*
+ * Setting of this flag indicates enabling of a byte counter for a given
+ * flow.
+ */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_BYTE_CTR UINT32_C(0x2)
+ /*
+ * Setting of this flag indicates enabling of a packet counter for a
+ * given flow.
+ */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PKT_CTR UINT32_C(0x4)
+ /*
+ * Setting of this flag indicates de-capsulation action for the given
+ * flow.
+ */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_DECAP UINT32_C(0x8)
+ /*
+ * Setting of this flag indicates encapsulation action for the given
+ * flow.
+ */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_ENCAP UINT32_C(0x10)
+ /*
+ * Setting of this flag indicates drop action. If this flag is not set,
+ * then it should be considered accept action.
+ */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_DROP UINT32_C(0x20)
+ uint32_t enables;
+ /* This bit must be '1' for the l2_filter_id field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_L2_FILTER_ID UINT32_C(0x1)
+ /* This bit must be '1' for the tunnel_type field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_TUNNEL_TYPE UINT32_C(0x2)
+ /* This bit must be '1' for the tunnel_id field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_TUNNEL_ID UINT32_C(0x4)
+ /* This bit must be '1' for the src_macaddr field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_SRC_MACADDR UINT32_C(0x8)
+ /* This bit must be '1' for the dst_macaddr field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_DST_MACADDR UINT32_C(0x10)
+ /* This bit must be '1' for the ovlan_vid field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_OVLAN_VID UINT32_C(0x20)
+ /* This bit must be '1' for the ivlan_vid field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_IVLAN_VID UINT32_C(0x40)
+ /* This bit must be '1' for the ethertype field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_ETHERTYPE UINT32_C(0x80)
+ /* This bit must be '1' for the src_ipaddr field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_SRC_IPADDR UINT32_C(0x100)
+ /* This bit must be '1' for the dst_ipaddr field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_DST_IPADDR UINT32_C(0x200)
+ /* This bit must be '1' for the ipaddr_type field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_IPADDR_TYPE UINT32_C(0x400)
+ /* This bit must be '1' for the ip_protocol field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_IP_PROTOCOL UINT32_C(0x800)
+ /* This bit must be '1' for the src_port field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_SRC_PORT UINT32_C(0x1000)
+ /* This bit must be '1' for the dst_port field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_DST_PORT UINT32_C(0x2000)
+ /* This bit must be '1' for the dst_id field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_DST_ID UINT32_C(0x4000)
+ /* This bit must be '1' for the mirror_vnic_id field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_MIRROR_VNIC_ID UINT32_C(0x8000)
+ /* This bit must be '1' for the encap_record_id field to be configured. */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_ENCAP_RECORD_ID UINT32_C(0x10000)
+ uint64_t l2_filter_id;
+ /*
+ * This value identifies a set of CFA data structures used for an L2
+ * context.
+ */
+ uint8_t tunnel_type;
+ /* Tunnel Type. */
+ /* Non-tunnel */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_NONTUNNEL UINT32_C(0x0)
+ /* Virtual eXtensible Local Area Network (VXLAN) */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1)
+ /* Network Virtualization Generic Routing Encapsulation (NVGRE) */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_NVGRE UINT32_C(0x2)
+ /* Generic Routing Encapsulation (GRE) inside Ethernet payload */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_L2GRE UINT32_C(0x3)
+ /* IP in IP */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_IPIP UINT32_C(0x4)
+ /* Generic Network Virtualization Encapsulation (Geneve) */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5)
+ /* Multi-Protocol Lable Switching (MPLS) */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_MPLS UINT32_C(0x6)
+ /* Stateless Transport Tunnel (STT) */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_STT UINT32_C(0x7)
+ /* Generic Routing Encapsulation (GRE) inside IP datagram payload */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_IPGRE UINT32_C(0x8)
+ /* Any tunneled traffic */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_ANYTUNNEL UINT32_C(0xff)
+ uint8_t unused_0;
+ uint16_t unused_1;
+ uint32_t tunnel_id;
+ /*
+ * Tunnel identifier. Virtual Network Identifier (VNI). Only valid with
+ * tunnel_types VXLAN, NVGRE, and Geneve. Only lower 24-bits of VNI
+ * field are used in setting up the filter.
+ */
+ uint8_t src_macaddr[6];
+ /* This value indicates the source MAC address in the Ethernet header. */
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t dst_macaddr[6];
+ /*
+ * This value indicates the destination MAC address in the Ethernet
+ * header.
+ */
+ uint16_t ovlan_vid;
+ /*
+ * This value indicates the VLAN ID of the outer VLAN tag in the
+ * Ethernet header.
+ */
+ uint16_t ivlan_vid;
+ /*
+ * This value indicates the VLAN ID of the inner VLAN tag in the
+ * Ethernet header.
+ */
+ uint16_t ethertype; /* big endian */
+ /* This value indicates the ethertype in the Ethernet header. */
+ uint8_t ip_addr_type;
+ /*
+ * This value indicates the type of IP address. 4 - IPv4 6 - IPv6 All
+ * others are invalid.
+ */
+ /* invalid */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_UNKNOWN UINT32_C(0x0)
+ /* IPv4 */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_IPV4 UINT32_C(0x4)
+ /* IPv6 */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 UINT32_C(0x6)
+ uint8_t ip_protocol;
+ /*
+ * The value of protocol filed in IP header. Applies to UDP and TCP
+ * traffic. 6 - UDP 17 - TCP
+ */
+ /* invalid */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_PROTOCOL_UNKNOWN UINT32_C(0x0)
+ /* UDP */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_PROTOCOL_UDP UINT32_C(0x6)
+ /* TCP */
+ #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_PROTOCOL_TCP UINT32_C(0x11)
+ uint8_t unused_4;
+ uint8_t unused_5;
+ uint32_t src_ipaddr[4]; /* big endian */
+ /*
+ * The value of source IP address to be used in filtering. For IPv4,
+ * first four bytes represent the IP address.
+ */
+ uint32_t dst_ipaddr[4]; /* big endian */
+ /*
+ * The value of destination IP address to be used in filtering. For
+ * IPv4, first four bytes represent the IP address.
+ */
+ uint16_t src_port; /* big endian */
+ /*
+ * The value of source port to be used in filtering. Applies to UDP and
+ * TCP traffic.
+ */
+ uint16_t dst_port; /* big endian */
+ /*
+ * The value of destination port to be used in filtering. Applies to UDP
+ * and TCP traffic.
+ */
+ uint16_t dst_id;
+ /*
+ * If set, this value shall represent the Logical VNIC ID of the
+ * destination VNIC for the RX path and network port id of the
+ * destination port for the TX path.
+ */
+ uint16_t mirror_vnic_id;
+ /* Logical VNIC ID of the VNIC where traffic is mirrored. */
+ uint32_t encap_record_id;
+ /* Logical ID of the encapsulation record. */
+ uint32_t unused_6;
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_cfa_em_flow_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint64_t em_filter_id;
+ /* This value is an opaque id into CFA data structures. */
+ uint32_t flow_id;
+ /*
+ * This is the ID of the flow associated with this filter. This value
+ * shall be used to match and associate the flow identifier returned in
+ * completion records. A value of 0xFFFFFFFF shall indicate no flow id.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_em_flow_free */
+/* Description: Free an EM flow table entry */
+/* Input (24 bytes) */
+
+struct hwrm_cfa_em_flow_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t em_filter_id;
+ /* This value is an opaque id into CFA data structures. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_cfa_em_flow_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_cfa_em_flow_cfg */
+/* Description: Configure an EM flow with new destination VNIC */
+/* Input (40 bytes) */
+
+struct hwrm_cfa_em_flow_cfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the new_dst_id field to be configured. */
+ #define HWRM_CFA_EM_FLOW_CFG_INPUT_ENABLES_NEW_DST_ID UINT32_C(0x1)
+ /*
+ * This bit must be '1' for the new_mirror_vnic_id field to be
+ * configured.
+ */
+ #define HWRM_CFA_EM_FLOW_CFG_INPUT_ENABLES_NEW_MIRROR_VNIC_ID UINT32_C(0x2)
+ uint32_t unused_0;
+ uint64_t em_filter_id;
+ /* This value is an opaque id into CFA data structures. */
+ uint32_t new_dst_id;
+ /*
+ * If set, this value shall represent the new Logical VNIC ID of the
+ * destination VNIC for the RX path and network port id of the
+ * destination port for the TX path.
+ */
+ uint32_t new_mirror_vnic_id;
+ /* New Logical VNIC ID of the VNIC where traffic is mirrored. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_cfa_em_flow_cfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_tunnel_dst_port_query */
+/*
+ * Description: This function is called by a driver to query tunnel type
+ * specific destination port configuration.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_tunnel_dst_port_query_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint8_t tunnel_type;
+ /* Tunnel Type. */
+ /* Virtual eXtensible Local Area Network (VXLAN) */
+ #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1)
+ /* Generic Network Virtualization Encapsulation (Geneve) */
+ #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5)
+ uint8_t unused_0[7];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_tunnel_dst_port_query_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t tunnel_dst_port_id;
+ /*
+ * This field represents the identifier of L4 destination port used for
+ * the given tunnel type. This field is valid for specific tunnel types
+ * that use layer 4 (e.g. UDP) transports for tunneling.
+ */
+ uint16_t tunnel_dst_port_val; /* big endian */
+ /*
+ * This field represents the value of L4 destination port identified by
+ * tunnel_dst_port_id. This field is valid for specific tunnel types
+ * that use layer 4 (e.g. UDP) transports for tunneling. This field is
+ * in network byte order. A value of 0 means that the destination port
+ * is not configured.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_tunnel_dst_port_alloc */
+/*
+ * Description: This function is called by a driver to allocate l4 destination
+ * port for a specific tunnel type. The destination port value is provided in
+ * the input. If the HWRM supports only one global destination port for a tunnel
+ * type, then the HWRM shall keep track of its usage as described below. # The
+ * first caller that allocates a destination port shall always succeed and the
+ * HWRM shall save the destination port configuration for that tunnel type and
+ * increment the usage count to 1. # Subsequent callers allocating the same
+ * destination port for that tunnel type shall succeed and the HWRM shall
+ * increment the usage count for that port for each subsequent caller that
+ * succeeds. # Any subsequent caller trying to allocate a different destination
+ * port for that tunnel type shall fail until the usage count for the original
+ * destination port goes to zero. # A caller that frees a port will cause the
+ * usage count for that port to decrement.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_tunnel_dst_port_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint8_t tunnel_type;
+ /* Tunnel Type. */
+ /* Virtual eXtensible Local Area Network (VXLAN) */
+ #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1)
+ /* Generic Network Virtualization Encapsulation (Geneve) */
+ #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5)
+ uint8_t unused_0;
+ uint16_t tunnel_dst_port_val; /* big endian */
+ /*
+ * This field represents the value of L4 destination port used for the
+ * given tunnel type. This field is valid for specific tunnel types that
+ * use layer 4 (e.g. UDP) transports for tunneling. This field is in
+ * network byte order. A value of 0 shall fail the command.
+ */
+ uint32_t unused_1;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_tunnel_dst_port_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t tunnel_dst_port_id;
+ /*
+ * Identifier of a tunnel L4 destination port value. Only applies to
+ * tunnel types that has l4 destination port parameters.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_tunnel_dst_port_free */
+/*
+ * Description: This function is called by a driver to free l4 destination port
+ * for a specific tunnel type.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_tunnel_dst_port_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint8_t tunnel_type;
+ /* Tunnel Type. */
+ /* Virtual eXtensible Local Area Network (VXLAN) */
+ #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1)
+ /* Generic Network Virtualization Encapsulation (Geneve) */
+ #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5)
+ uint8_t unused_0;
+ uint16_t tunnel_dst_port_id;
+ /*
+ * Identifier of a tunnel L4 destination port value. Only applies to
+ * tunnel types that has l4 destination port parameters.
+ */
+ uint32_t unused_1;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_tunnel_dst_port_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_stat_ctx_alloc */
+/*
+ * Description: This command allocates and does basic preparation for a stat
+ * context.
+ */
+/* Input (32 bytes) */
+
+struct hwrm_stat_ctx_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t stats_dma_addr;
+ /* This is the address for statistic block. */
+ uint32_t update_period_ms;
+ /*
+ * The statistic block update period in ms. e.g. 250ms, 500ms, 750ms,
+ * 1000ms.
+ */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_stat_ctx_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t stat_ctx_id;
+ /* This is the statistics context ID value. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_stat_ctx_free */
+/* Description: This command is used to free a stat context. */
+/* Input (24 bytes) */
+
+struct hwrm_stat_ctx_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t stat_ctx_id;
+ /* ID of the statistics context that is being queried. */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_stat_ctx_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t stat_ctx_id;
+ /* This is the statistics context ID value. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_stat_ctx_query */
+/* Description: This command returns statistics of a context. */
+/* Input (24 bytes) */
+
+struct hwrm_stat_ctx_query_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t stat_ctx_id;
+ /* ID of the statistics context that is being queried. */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (176 bytes) */
+
+struct hwrm_stat_ctx_query_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint64_t tx_ucast_pkts;
+ /* Number of transmitted unicast packets */
+ uint64_t tx_mcast_pkts;
+ /* Number of transmitted multicast packets */
+ uint64_t tx_bcast_pkts;
+ /* Number of transmitted broadcast packets */
+ uint64_t tx_err_pkts;
+ /* Number of transmitted packets with error */
+ uint64_t tx_drop_pkts;
+ /* Number of dropped packets on transmit path */
+ uint64_t tx_ucast_bytes;
+ /* Number of transmitted bytes for unicast traffic */
+ uint64_t tx_mcast_bytes;
+ /* Number of transmitted bytes for multicast traffic */
+ uint64_t tx_bcast_bytes;
+ /* Number of transmitted bytes for broadcast traffic */
+ uint64_t rx_ucast_pkts;
+ /* Number of received unicast packets */
+ uint64_t rx_mcast_pkts;
+ /* Number of received multicast packets */
+ uint64_t rx_bcast_pkts;
+ /* Number of received broadcast packets */
+ uint64_t rx_err_pkts;
+ /* Number of received packets with error */
+ uint64_t rx_drop_pkts;
+ /* Number of dropped packets on received path */
+ uint64_t rx_ucast_bytes;
+ /* Number of received bytes for unicast traffic */
+ uint64_t rx_mcast_bytes;
+ /* Number of received bytes for multicast traffic */
+ uint64_t rx_bcast_bytes;
+ /* Number of received bytes for broadcast traffic */
+ uint64_t rx_agg_pkts;
+ /* Number of aggregated unicast packets */
+ uint64_t rx_agg_bytes;
+ /* Number of aggregated unicast bytes */
+ uint64_t rx_agg_events;
+ /* Number of aggregation events */
+ uint64_t rx_agg_aborts;
+ /* Number of aborted aggregations */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_stat_ctx_clr_stats */
+/* Description: This command clears statistics of a context. */
+/* Input (24 bytes) */
+
+struct hwrm_stat_ctx_clr_stats_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t stat_ctx_id;
+ /* ID of the statistics context that is being queried. */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_stat_ctx_clr_stats_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_fw_reset */
+/*
+ * Description: This function is called by a driver to self reset the firmware
+ * running on the processor indicated by the embedded_proc_type.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_fw_reset_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint8_t embedded_proc_type;
+ /* Type of embedded processor. */
+ /* Boot Processor */
+ #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_BOOT UINT32_C(0x0)
+ /* Management Processor */
+ #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_MGMT UINT32_C(0x1)
+ /* Network control processor */
+ #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_NETCTRL UINT32_C(0x2)
+ /* RoCE control processor */
+ #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_ROCE UINT32_C(0x3)
+ /* Reserved */
+ #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_RSVD UINT32_C(0x4)
+ uint8_t selfrst_status;
+ /* Type of self reset. */
+ /* No Self Reset */
+ #define HWRM_FW_RESET_INPUT_SELFRST_STATUS_SELFRSTNONE UINT32_C(0x0)
+ /* Self Reset as soon as possible to do so safely */
+ #define HWRM_FW_RESET_INPUT_SELFRST_STATUS_SELFRSTASAP UINT32_C(0x1)
+ /* Self Reset on PCIe Reset */
+ #define HWRM_FW_RESET_INPUT_SELFRST_STATUS_SELFRSTPCIERST UINT32_C(0x2)
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_fw_reset_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t selfrst_status;
+ /* Type of self reset. */
+ /* No Self Reset */
+ #define HWRM_FW_RESET_OUTPUT_SELFRST_STATUS_SELFRSTNONE UINT32_C(0x0)
+ /* Self Reset as soon as possible to do so safely */
+ #define HWRM_FW_RESET_OUTPUT_SELFRST_STATUS_SELFRSTASAP UINT32_C(0x1)
+ /* Self Reset on PCIe Reset */
+ #define HWRM_FW_RESET_OUTPUT_SELFRST_STATUS_SELFRSTPCIERST UINT32_C(0x2)
+ uint8_t unused_0;
+ uint16_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_fw_qstatus */
+/*
+ * Description: This function is called by a driver to query the status of the
+ * firmware running on the processor indicated by the embedded_proc_type.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_fw_qstatus_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint8_t embedded_proc_type;
+ /* Type of embedded processor. */
+ /* Boot Processor */
+ #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_BOOT UINT32_C(0x0)
+ /* Management Processor */
+ #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_MGMT UINT32_C(0x1)
+ /* Network control processor */
+ #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_NETCTRL UINT32_C(0x2)
+ /* RoCE control processor */
+ #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_ROCE UINT32_C(0x3)
+ /* Reserved */
+ #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_RSVD UINT32_C(0x4)
+ uint8_t unused_0[7];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_fw_qstatus_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t selfrst_status;
+ /* Type of self reset. */
+ /* No Self Reset */
+ #define HWRM_FW_QSTATUS_OUTPUT_SELFRST_STATUS_SELFRSTNONE UINT32_C(0x0)
+ /* Self Reset as soon as possible to do so safely */
+ #define HWRM_FW_QSTATUS_OUTPUT_SELFRST_STATUS_SELFRSTASAP UINT32_C(0x1)
+ /* Self Reset on PCIe Reset */
+ #define HWRM_FW_QSTATUS_OUTPUT_SELFRST_STATUS_SELFRSTPCIERST UINT32_C(0x2)
+ uint8_t unused_0;
+ uint16_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_fw_set_time */
+/*
+ * Description: Inform the HWRM firmware of the current date/time. Ideally, the
+ * date/time will be current time in GMT/UTC and the zone value will be 0
+ * (indicating UTC). If the time zone is not known, the zone value shall be
+ * 0xffff. Other values for zone are discouraged, but if specified, they
+ * indicate the number of minutes east of UTC, while zones west of UTC are
+ * represented with a 2's complement negative value (e.g. PST would be -480
+ * while PDT would be -420).
+ */
+/* Input (32 bytes) */
+
+struct hwrm_fw_set_time_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t year;
+ /* Current year */
+ /* Date/time is not known */
+ #define HWRM_FW_SET_TIME_INPUT_YEAR_UNKNOWN UINT32_C(0x0)
+ uint8_t month;
+ /* Current month of year (1-12) */
+ uint8_t day;
+ /* Current day of month (1-31) */
+ uint8_t hour;
+ /* Current hour (0-23) */
+ uint8_t minute;
+ /* Current minute (0-59) */
+ uint8_t second;
+ /* Current second (0-59) */
+ uint8_t unused_0;
+ uint16_t millisecond;
+ /* Current millisecond (0-999) */
+ uint16_t zone;
+ /* Minutes east of UTC, 0xffff if TZ is not known */
+ /* Time zone is Coordinated Universal Time (UTC) */
+ #define HWRM_FW_SET_TIME_INPUT_ZONE_UTC UINT32_C(0x0)
+ /* Time zone is not known */
+ #define HWRM_FW_SET_TIME_INPUT_ZONE_UNKNOWN UINT32_C(0xffff)
+ uint32_t unused_1;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_fw_set_time_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_fw_get_time */
+/* Description: Query the HWRM firmware's notion of the current date/time. */
+/* Input (16 bytes) */
+
+struct hwrm_fw_get_time_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_fw_get_time_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t year;
+ /* Current year */
+ /* Date/time is not known */
+ #define HWRM_FW_GET_TIME_OUTPUT_YEAR_UNKNOWN UINT32_C(0x0)
+ uint8_t month;
+ /* Current month of year (1-12) */
+ uint8_t day;
+ /* Current day of month (1-31) */
+ uint8_t hour;
+ /* Current hour (0-23) */
+ uint8_t minute;
+ /* Current minute (0-59) */
+ uint8_t second;
+ /* Current second (0-59) */
+ uint8_t unused_0;
+ uint16_t millisecond;
+ /* Current millisecond (0-999) */
+ uint16_t zone;
+ /* Minutes east of UTC, 0xffff if TZ is not known */
+ /* Time zone is Coordinated Universal Time (UTC) */
+ #define HWRM_FW_GET_TIME_OUTPUT_ZONE_UTC UINT32_C(0x0)
+ /* Time zone is not known */
+ #define HWRM_FW_GET_TIME_OUTPUT_ZONE_UNKNOWN UINT32_C(0xffff)
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_exec_fwd_resp */
+/*
+ * Description: This command is used to send an encapsulated request to the
+ * HWRM. This command instructs the HWRM to execute the request and forward the
+ * response of the encapsulated request to the location specified in the
+ * original request that is encapsulated. The target id of this command shall be
+ * set to 0xFFFF (HWRM). The response location in this command shall be used to
+ * acknowledge the receipt of the encapsulated request and forwarding of the
+ * response.
+ */
+/* Input (128 bytes) */
+
+struct hwrm_exec_fwd_resp_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t encap_request[26];
+ /*
+ * This is an encapsulated request. This request should be executed by
+ * the HWRM and the response should be provided in the response buffer
+ * inside the encapsulated request.
+ */
+ uint16_t encap_resp_target_id;
+ /*
+ * This value indicates the target id of the response to the
+ * encapsulated request. 0x0 - 0xFFF8 - Used for function ids 0xFFF8 -
+ * 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_exec_fwd_resp_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_reject_fwd_resp */
+/*
+ * Description: This command is used to send an encapsulated request to the
+ * HWRM. This command instructs the HWRM to reject the request and forward the
+ * error response of the encapsulated request to the location specified in the
+ * original request that is encapsulated. The target id of this command shall be
+ * set to 0xFFFF (HWRM). The response location in this command shall be used to
+ * acknowledge the receipt of the encapsulated request and forwarding of the
+ * response.
+ */
+/* Input (128 bytes) */
+
+struct hwrm_reject_fwd_resp_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t encap_request[26];
+ /*
+ * This is an encapsulated request. This request should be rejected by
+ * the HWRM and the error response should be provided in the response
+ * buffer inside the encapsulated request.
+ */
+ uint16_t encap_resp_target_id;
+ /*
+ * This value indicates the target id of the response to the
+ * encapsulated request. 0x0 - 0xFFF8 - Used for function ids 0xFFF8 -
+ * 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_reject_fwd_resp_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_fwd_resp */
+/*
+ * Description: This command is used to send an encapsulated response to the
+ * HWRM. The HWRM shall forward this response based on the target id. The
+ * response address provided in this command shall be used to acknowledge the
+ * receipt of the encapsulated response. The encapsulated response address
+ * provided in this command shall be used to provide the encapsulated response.
+ */
+/* Input (40 bytes) */
+
+struct hwrm_fwd_resp_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t encap_resp_target_id;
+ /*
+ * This value indicates the target id of the encapsulated response. 0x0
+ * - 0xFFF8 - Used for function ids 0xFFF8 - 0xFFFE - Reserved for
+ * internal processors 0xFFFF - HWRM
+ */
+ uint16_t encap_resp_cmpl_ring;
+ /*
+ * This value indicates the completion ring the encapsulated response
+ * will be optionally completed on. If the value is -1, then no CR
+ * completion shall be generated for the encapsulated response. Any
+ * other value must be a valid CR ring_id value. If a valid
+ * encap_resp_cmpl_ring is provided, then a CR completion shall be
+ * generated for the encapsulated response.
+ */
+ uint16_t encap_resp_len;
+ /* This field indicates the length of encapsulated response. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint64_t encap_resp_addr;
+ /*
+ * This is the host address where the encapsulated response will be
+ * written. This area must be 16B aligned and must be cleared to zero
+ * before the original request is made.
+ */
+ uint32_t encap_resp[24];
+ /* This is an encapsulated response. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_fwd_resp_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_fwd_async_event_cmpl */
+/*
+ * Description: This command is used to send an encapsulated asynchronous event
+ * completion to the HWRM. The HWRM shall forward this asynchronous event
+ * completion to target(s) specified in the command. The HWRM shall complete
+ * this command only after forwarding asynchronous event completion to specified
+ * targets.
+ */
+/* Input (32 bytes) */
+
+struct hwrm_fwd_async_event_cmpl_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t encap_async_event_target_id;
+ /*
+ * This value indicates the target id of the encapsulated asynchronous
+ * event. 0x0 - 0xFFF8 - Used for function ids 0xFFF8 - 0xFFFE -
+ * Reserved for internal processors 0xFFFF - Broadcast to all children
+ * VFs (only applicable when a PF is the requester)
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2[3];
+ uint8_t unused_3;
+ uint32_t encap_async_event_cmpl[4];
+ /* This is an encapsulated asynchronous event completion. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_fwd_async_event_cmpl_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_temp_monitor_query */
+/*
+ * Description: A temperature monitor is used to query the device temperature.
+ */
+/* Input (16 bytes) */
+
+struct hwrm_temp_monitor_query_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_temp_monitor_query_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t temp;
+ /* The HWRM shall provide the current temperature of device in Celsius. */
+ uint8_t unused_0;
+ uint16_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_wol_filter_alloc */
+/*
+ * Description: A Wake-On-LAN (WoL) filter is a filter resource that is used to
+ * identify a WoL packet. # Among all function drivers, the HWRM shall only
+ * allow PF drivers to allocate WoL filters. # The HWRM shall not allow VF
+ * drivers to allocate any WoL filters. # When partitioning is enabled and WoL
+ * is supported, the HWRM shall support at least one WoL filter per partition. #
+ * The HWRM shall retain a WoL filter setting until the filter is freed. # If
+ * the HWRM client is a function driver, then the HWRM shall not allow the HWRM
+ * client to set up WoL filters on the port that the function is not associated
+ * with. # If the HWRM client is one of the trusted embedded services (e.g.
+ * management service), the the HWRM shall allow the HWRM client to set up WoL
+ * filters on any port of the device.
+ */
+/* Input (64 bytes) */
+
+struct hwrm_wol_filter_alloc_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ uint32_t enables;
+ /* This bit must be '1' for the mac_address field to be configured. */
+ #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS UINT32_C(0x1)
+ /* This bit must be '1' for the pattern_offset field to be configured. */
+ #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_PATTERN_OFFSET UINT32_C(0x2)
+ /* This bit must be '1' for the pattern_buf_size field to be configured. */
+ #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_PATTERN_BUF_SIZE UINT32_C(0x4)
+ /* This bit must be '1' for the pattern_buf_addr field to be configured. */
+ #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_PATTERN_BUF_ADDR UINT32_C(0x8)
+ /*
+ * This bit must be '1' for the pattern_mask_addr field to be
+ * configured.
+ */
+ #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_PATTERN_MASK_ADDR UINT32_C(0x10)
+ /*
+ * This bit must be '1' for the pattern_mask_size field to be
+ * configured.
+ */
+ #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_PATTERN_MASK_SIZE UINT32_C(0x20)
+ uint16_t port_id;
+ /* Port ID of port on which WoL filter is configured. */
+ uint8_t wol_type;
+ /* This value represents a Wake-on-LAN type. */
+ /* Magic Paket */
+ #define HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT UINT32_C(0x0)
+ /* Bitmap */
+ #define HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_BMP UINT32_C(0x1)
+ /* Invalid */
+ #define HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_INVALID UINT32_C(0xff)
+ uint8_t unused_0;
+ uint32_t unused_1;
+ uint8_t mac_address[6];
+ /*
+ * # If this field is enabled and magic packet WoL filter type is
+ * specified in this command, the value set in this field shall be used
+ * in setting the magic packet based WoL filter. # If this field is not
+ * enabled and magic packet WoL filter type is specified and port id is
+ * specified to 0xFF in this command, then the HWRM shall use default
+ * MAC address configured on the function associated with the HWRM
+ * client. # If this field is not enabled and magic packet WoL filter
+ * type is specified and port id is not specified to 0xFF in this
+ * command, then the HWRM shall use default MAC address configured on
+ * the port.
+ */
+ uint16_t pattern_offset;
+ /*
+ * The offset from the beginning of MAC header where pattern should be
+ * matched. Applies to bitmap WoL.
+ */
+ uint16_t pattern_buf_size;
+ /* The size of the pattern that is being matched. Applies to bitmap WoL. */
+ uint16_t pattern_mask_size;
+ /* The size of the pattern mask. Applies to bitmap WoL. */
+ uint32_t unused_2;
+ uint64_t pattern_buf_addr;
+ /* Physical address of the pattern buffer. Applies to bitmap WoL. */
+ uint64_t pattern_mask_addr;
+ /* Physical address of the pattern mask. Applies to bitmap WoL. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_wol_filter_alloc_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t wol_filter_id;
+ /* This value identifies a Wake-on-LAN (WoL) filter. */
+ uint8_t unused_0;
+ uint16_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_wol_filter_free */
+/*
+ * Description: Free a WoL filter. # Among all function drivers, the HWRM shall
+ * only allow PF drivers to free WoL filters. # The HWRM shall not allow VF
+ * drivers to free any WoL filters. # The HWRM shall not allow a function driver
+ * to free an Out-Of-Box WoL filter. # The HWRM shall not allow a function
+ * driver to free a WoL filter on a port that the corresponding function is not
+ * associated with. # The HWRM shall not allow a function driver to free a WoL
+ * filter on a function that the function driver is not associated with.
+ */
+/* Input (32 bytes) */
+
+struct hwrm_wol_filter_free_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t flags;
+ /*
+ * # When this bit is set to '1', then all active WoL filters on the
+ * port are requested to be freed. # If the a function driver sets this
+ * flag to '1', then the HWRM shall free all active WoL filters that are
+ * not set by other function drivers on that port.
+ */
+ #define HWRM_WOL_FILTER_FREE_INPUT_FLAGS_FREE_ALL_WOL_FILTERS UINT32_C(0x1)
+ uint32_t enables;
+ /* This bit must be '1' for the wol_filter_id field to be configured. */
+ #define HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID UINT32_C(0x1)
+ uint16_t port_id;
+ /* Port ID of the port on which WoL filter(s) is (are) being freed. */
+ uint8_t wol_filter_id;
+ /* The HWRM shall ignore this field if free_all_wol_filters flag is set. */
+ uint8_t unused_0[5];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_wol_filter_free_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_wol_filter_qcfg */
+/*
+ * Description: Query WoL filter configuration. # Among all function drivers,
+ * the HWRM shall only allow PF drivers to query WoL filters. # The HWRM shall
+ * not allow VF drivers to query any WoL filters. # The HWRM shall return WoL
+ * filters that are active on the associated port for which this query is being
+ * performed. # If the HWRM client is a function driver, then the HWRM shall not
+ * allow the HWRM client to query WoL filters that are set up by other function
+ * drivers. # If the HWRM client is a function driver, then the HWRM shall not
+ * allow the HWRM client to query WoL filters on the port that the function is
+ * not associated with. # If the HWRM client is one of the trusted embedded
+ * service (e.g. management service), the the HWRM shall allow the HWRM client
+ * to query WoL filters on any port of the device.
+ */
+/* Input (56 bytes) */
+
+struct hwrm_wol_filter_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t port_id;
+ /* Port ID of port on which WoL filter that is being queried. */
+ uint16_t handle;
+ /*
+ * This is an opaque handle used to access filters. # The HWRM client
+ * shall set this field to 0x0000 to begin the query. # After the first
+ * query, the HWRM client shall retrieve next filters (if they exist)
+ * using the HWRM provided handle in the response.
+ */
+ uint32_t unused_0;
+ uint64_t pattern_buf_addr;
+ /*
+ * Physical address of the pattern buffer. Applies to bitmap WoL filter
+ * only. # Value of 0 indicates an invalid buffer address. If this field
+ * is set to 0, then HWRM shall ignore pattern_buf_size. # If the HWRM
+ * client provides an invalid buffer address for the pattern, then the
+ * HWRM is not required to provide pattern when the response contains a
+ * bitmap WoL filter.
+ */
+ uint64_t pattern_buf_size;
+ /* The sixe of the pattern buffer. Applies to bitmap WoL filter only. */
+ uint64_t pattern_mask_addr;
+ /*
+ * Physical address of the pattern mask. Applies to bitmap WoL filter
+ * only. # Value of 0 indicates an invalid pattern mask address. If this
+ * field is set to 0, then HWRM shall ignore pattern_mask_size. # If the
+ * HWRM client provides an invalid mask address for the pattern, then
+ * the HWRM is not required to provide mask when the response contains a
+ * bitmap WoL filter.
+ */
+ uint64_t pattern_mask_size;
+ /*
+ * The size of the buffer for pattern mask. Applies to bitmap WoL filter
+ * only.
+ */
+} __attribute__((packed));
+
+/* Output (32 bytes) */
+
+struct hwrm_wol_filter_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t next_handle;
+ /*
+ * This is the next handle that is used to access filters. # If this
+ * field is set to 0x0000, then no WoL filters are currently configured
+ * on this port and all other fields in the output shall be ignored by
+ * the HWRM client. # If this field is set to neither 0x0000 nor 0xFFFF,
+ * then the wol_filter_id is valid and the parameters provided in the
+ * response are based on the wol_type. # If this field is set to 0xFFFF,
+ * then there are no remaining configured WoL filters to be queried for
+ * the queried function after this response, wol_filter_id is valid and
+ * the parameters provided in the response are based on the wol_type.
+ */
+ uint8_t wol_filter_id;
+ /* This value identifies the filter returned in this response. */
+ uint8_t wol_type;
+ /*
+ * This value identifies the type of WoL filter returned in this
+ * response.
+ */
+ /* Magic Paket */
+ #define HWRM_WOL_FILTER_QCFG_OUTPUT_WOL_TYPE_MAGICPKT UINT32_C(0x0)
+ /* Bitmap */
+ #define HWRM_WOL_FILTER_QCFG_OUTPUT_WOL_TYPE_BMP UINT32_C(0x1)
+ /* Invalid */
+ #define HWRM_WOL_FILTER_QCFG_OUTPUT_WOL_TYPE_INVALID UINT32_C(0xff)
+ uint32_t unused_0;
+ uint8_t mac_address[6];
+ /*
+ * The MAC address value used by the WoL filter. Applies to magic packet
+ * based WoL.
+ */
+ uint16_t pattern_offset;
+ /*
+ * The offset from the beginning of MAC header where pattern should be
+ * matched. Applies to bitmap WoL.
+ */
+ uint16_t pattern_size;
+ /*
+ * The actual size of the pattern that is being returned. Applies to
+ * bitmap WoL.
+ */
+ uint16_t pattern_mask_size;
+ /*
+ * The actual size of the pattern mask that is being returned. Applies
+ * to bitmap WoL.
+ */
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_wol_reason_qcfg */
+/* Description: Query WoL reason for the last system wake up. */
+/* Input (40 bytes) */
+
+struct hwrm_wol_reason_qcfg_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t port_id;
+ /* Port ID of port for which this query is for. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2[3];
+ uint8_t unused_3;
+ uint64_t wol_pkt_buf_addr;
+ /* Physical address of the packet buffer for querying WoL packet. */
+ uint64_t wol_pkt_buf_size;
+ /* The size of the buffer for the WoL packet. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_wol_reason_qcfg_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint8_t wol_filter_id;
+ /*
+ * This value identifies the filter that matched the last WoL packet.
+ * This id is only valid with valid WoL reason.
+ */
+ uint8_t wol_reason;
+ /*
+ * This value identifies the type of WoL reason returned in this
+ * response. When the wol_type is set to invalid, then there is no WoL
+ * event that happened during last system wake-up.
+ */
+ /* Magic Paket */
+ #define HWRM_WOL_REASON_QCFG_OUTPUT_WOL_REASON_MAGICPKT UINT32_C(0x0)
+ /* Bitmap */
+ #define HWRM_WOL_REASON_QCFG_OUTPUT_WOL_REASON_BMP UINT32_C(0x1)
+ /* Invalid */
+ #define HWRM_WOL_REASON_QCFG_OUTPUT_WOL_REASON_INVALID UINT32_C(0xff)
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t unused_4;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_dbg_dump */
+/*
+ * Description: This command is used by to initiate the dump of debug
+ * information to a driver specified address.
+ */
+/* Input (40 bytes) */
+
+struct hwrm_dbg_dump_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t handle;
+ /*
+ * Handle used to dump debug data. handle = 0 indicates the beginning of
+ * the dump. handle != 0 indicates the request to dump the next part.
+ */
+ uint32_t unused_0;
+ uint64_t host_dbg_dump_addr;
+ /*
+ * Address of the host buffer where the debug data is requested to be
+ * dumped.
+ */
+ uint64_t host_dbg_dump_addr_len;
+ /* Length of host buffer used for transferring debug data. */
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_dbg_dump_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t nexthandle;
+ /*
+ * Handle used to indicate availability of additional debug data.
+ * nexthandle = 0 indicates that there is no more debug data available.
+ * nexthandle != 0 indicates the handle value that should be used to
+ * request the next part of debug data.
+ */
+ uint32_t dbg_data_len;
+ /* The number of bytes of debug data written to debug dump buffer. */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_raw_write_blk */
+/*
+ * Note: Write an unmanaged block of data at any physical offset within the
+ * NVRAM. Used for initial provisioning/manufacturing purposes only. Implemented
+ * in the ChiMP boot-strap firmware (fwutil.bin) only.
+ */
+/* Input (32 bytes) */
+
+struct hwrm_nvm_raw_write_blk_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t host_src_addr;
+ /*
+ * 64-bit Host Source Address. This is the loation of the source data to
+ * be written.
+ */
+ uint32_t dest_addr;
+ /*
+ * 32-bit Destination Address. This is the NVRAM byte-offset where the
+ * source data will be written to.
+ */
+ uint32_t len;
+ /* Length of data to be written, in bytes. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_nvm_raw_write_blk_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_read */
+/*
+ * Note: Read the contents of an NVRAM item as referenced (indexed) by an
+ * existing directory entry.
+ */
+/* Input (40 bytes) */
+
+struct hwrm_nvm_read_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t host_dest_addr;
+ /*
+ * 64-bit Host Destination Address. This is the host address where the
+ * data will be written to.
+ */
+ uint16_t dir_idx;
+ /* The 0-based index of the directory entry. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint32_t offset;
+ /* The NVRAM byte-offset to read from. */
+ uint32_t len;
+ /* The length of the data to be read, in bytes. */
+ uint32_t unused_2;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_nvm_read_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_raw_dump */
+/* Note: Dump a raw block of data from NVRAM. */
+/* Input (32 bytes) */
+
+struct hwrm_nvm_raw_dump_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t host_dest_addr;
+ /*
+ * 64-bit Host Destination Address. This is the host address where the
+ * data will be written to.
+ */
+ uint32_t offset;
+ /* 32-bit NVRAM byte-offset to read from. */
+ uint32_t len;
+ /* Total length of NVRAM contents to be read, in bytes. */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_nvm_raw_dump_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_get_dir_entries */
+/*
+ * Description: Read the NVRAM directory. Each directory entry is at least 24
+ * bytes in length and contains the: - 16-bit directory entry type
+ * (BNX_DIR_TYPE_* value) - 16-bit ordinal (instance of this directory entry
+ * type) - 16-bit extension flags (identifies inactive entries and entries for
+ * firmware update) - 16-bit attribute flags (identifies entries with a
+ * purposely invalid chksum value) - 32-bit byte-offset into NVRAM where this
+ * item data is located - 32-bit length of allocated NVRAM for item, in bytes
+ * (multiple of block size) - 32-bit length of data (excluding padding), in
+ * bytes (may be 0) - 32-bit data checksum (CRC-32) See the
+ * bnxnvm_directory_entry_t definition in the file bnxnvm_defs.h.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_nvm_get_dir_entries_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t host_dest_addr;
+ /*
+ * 64-bit Host Destination Address. This is the host address where the
+ * directory will be written.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_nvm_get_dir_entries_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_get_dir_info */
+/* Note: Get Directory Header info. */
+/* Input (16 bytes) */
+
+struct hwrm_nvm_get_dir_info_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_nvm_get_dir_info_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t entries;
+ /* Number of directory entries in the directory. */
+ uint32_t entry_length;
+ /* Size of each directory entry, in bytes. */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_write */
+/*
+ * Note: Write to the allocated NVRAM of an item referenced by an existing
+ * directory entry.
+ */
+/* Input (48 bytes) */
+
+struct hwrm_nvm_write_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t host_src_addr;
+ /* 64-bit Host Source Address. This is where the source data is. */
+ uint16_t dir_type;
+ /*
+ * The Directory Entry Type (valid values are defined in the
+ * bnxnvm_directory_type enum defined in the file bnxnvm_defs.h).
+ */
+ uint16_t dir_ordinal;
+ /*
+ * Directory ordinal. The 0-based instance of the combined Directory
+ * Entry Type and Extension.
+ */
+ uint16_t dir_ext;
+ /*
+ * The Directory Entry Extension flags (see BNX_DIR_EXT_* in the file
+ * bnxnvm_defs.h).
+ */
+ uint16_t dir_attr;
+ /*
+ * Directory Entry Attribute flags (see BNX_DIR_ATTR_* in the file
+ * bnxnvm_defs.h).
+ */
+ uint32_t dir_data_length;
+ /*
+ * Length of data to write, in bytes. May be less than or equal to the
+ * allocated size for the directory entry. The data length stored in the
+ * directory entry will be updated to reflect this value once the write
+ * is complete.
+ */
+ uint16_t option;
+ /* Option. */
+ uint16_t flags;
+ /*
+ * When this bit is '1', the original active image will not be removed.
+ * TBD: what purpose is this?
+ */
+ #define HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG UINT32_C(0x1)
+ uint32_t dir_item_length;
+ /*
+ * The requested length of the allocated NVM for the item, in bytes.
+ * This value may be greater than or equal to the specified data length
+ * (dir_data_length). If this value is less than the specified data
+ * length, it will be ignored. The response will contain the actual
+ * allocated item length, which may be greater than the requested item
+ * length. The purpose for allocating more than the required number of
+ * bytes for an item's data is to pre-allocate extra storage (padding)
+ * to accommodate the potential future growth of an item (e.g. upgraded
+ * firmware with a size increase, log growth, expanded configuration
+ * data).
+ */
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_nvm_write_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t dir_item_length;
+ /*
+ * Length of the allocated NVM for the item, in bytes. The value may be
+ * greater than or equal to the specified data length or the requested
+ * item length. The actual item length used when creating a new
+ * directory entry will be a multiple of an NVM block size.
+ */
+ uint16_t dir_idx;
+ /* The directory index of the created or modified item. */
+ uint8_t unused_0;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_modify */
+/*
+ * Note: Modify the contents of an NVRAM item as referenced (indexed) by an
+ * existing directory entry.
+ */
+/* Input (40 bytes) */
+
+struct hwrm_nvm_modify_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint64_t host_src_addr;
+ /* 64-bit Host Source Address. This is where the modified data is. */
+ uint16_t dir_idx;
+ /* 16-bit directory entry index. */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint32_t offset;
+ /* 32-bit NVRAM byte-offset to modify content from. */
+ uint32_t len;
+ /*
+ * Length of data to be modified, in bytes. The length shall be non-
+ * zero.
+ */
+ uint32_t unused_2;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_nvm_modify_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_find_dir_entry */
+/*
+ * Note: Search a directory entry in the directory by either directory entry
+ * index or directory entry parameters.
+ */
+/* Input (32 bytes) */
+
+struct hwrm_nvm_find_dir_entry_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the dir_idx_valid field to be configured. */
+ #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID UINT32_C(0x1)
+ uint16_t dir_idx;
+ /* Directory Entry Index */
+ uint16_t dir_type;
+ /* Directory Entry (Image) Type */
+ uint16_t dir_ordinal;
+ /* Directory ordinal. The instance of this Directory Type */
+ uint16_t dir_ext;
+ /* The Directory Entry Extension flags. */
+ uint8_t opt_ordinal;
+ /* This value indicates the search option using dir_ordinal. */
+ #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_MASK UINT32_C(0x3)
+ #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_SFT 0
+ /* Equal to specified ordinal value. */
+ #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_EQ UINT32_C(0x0)
+ /* Greater than or equal to specified ordinal value */
+ #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_GE UINT32_C(0x1)
+ /* Greater than specified ordinal value */
+ #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_GT UINT32_C(0x2)
+ uint8_t unused_1[3];
+} __attribute__((packed));
+
+/* Output (32 bytes) */
+
+struct hwrm_nvm_find_dir_entry_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t dir_item_length;
+ /* Allocated NVRAM for this directory entry, in bytes. */
+ uint32_t dir_data_length;
+ /* Size of the stored data for this directory entry, in bytes. */
+ uint32_t fw_ver;
+ /*
+ * Firmware version. Only valid if the directory entry is for embedded
+ * firmware stored in APE_BIN Format.
+ */
+ uint16_t dir_ordinal;
+ /* Directory ordinal. */
+ uint16_t dir_idx;
+ /* Directory Entry Index */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_erase_dir_entry */
+/*
+ * Note: Remove a directory entry specified by the directory entry index from
+ * the directory.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_nvm_erase_dir_entry_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t dir_idx;
+ /* Directory Entry Index */
+ uint16_t unused_0[3];
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_nvm_erase_dir_entry_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_get_dev_info */
+/*
+ * Note: Get device info. Return Manufacturer_ID, Device_ID, block_size,
+ * nvram_size, reserved_size and available_size.
+ */
+/* Input (16 bytes) */
+
+struct hwrm_nvm_get_dev_info_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+} __attribute__((packed));
+
+/* Output (32 bytes) */
+
+struct hwrm_nvm_get_dev_info_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint16_t manufacturer_id;
+ /* Manufacturer ID. */
+ uint16_t device_id;
+ /* Device ID. */
+ uint32_t sector_size;
+ /* Sector size of the NVRAM device. */
+ uint32_t nvram_size;
+ /* Total size, in bytes of the NVRAM device. */
+ uint32_t reserved_size;
+ uint32_t available_size;
+ /*
+ * Available size that can be used, in bytes. Available size is the
+ * NVRAM size take away the used size and reserved size.
+ */
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_mod_dir_entry */
+/* Note: Modify a directory entry parameters in the directory. */
+/* Input (32 bytes) */
+
+struct hwrm_nvm_mod_dir_entry_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t enables;
+ /* This bit must be '1' for the checksum field to be configured. */
+ #define HWRM_NVM_MOD_DIR_ENTRY_INPUT_ENABLES_CHECKSUM UINT32_C(0x1)
+ uint16_t dir_idx;
+ /* Directory Entry Index */
+ uint16_t dir_ordinal;
+ /* Directory ordinal. The (0-based) instance of this Directory Type. */
+ uint16_t dir_ext;
+ /*
+ * The Directory Entry Extension flags (see BNX_DIR_EXT_* for extension
+ * flag definitions).
+ */
+ uint16_t dir_attr;
+ /*
+ * Directory Entry Attribute flags (see BNX_DIR_ATTR_* for attribute
+ * flag definitions).
+ */
+ uint32_t checksum;
+ /*
+ * If valid, then this field updates the checksum value of the content
+ * in the directory entry.
+ */
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_nvm_mod_dir_entry_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_verify_update */
+/*
+ * Description: Verify updated content of a directory entry. Before this
+ * verification, there should be two valid directory entries of the given
+ * directory type (one with "UPDATE" directory extension flag and the current
+ * one "ACTIVE"). Below are steps the HWRM performs for executing this command:
+ * # The HWRM finds the directory entry with "UDPATE" extension flag based on
+ * input parameters. The new directory entry should already have updated
+ * contents. # The HWRM performs signature verification of the updated content.
+ * # If the signature verification is successful, the two directory entries are
+ * switched (the verified updated entry is made active and the current "ACTIVE"
+ * entry is marked with "UPDATE" extension flag). Implementation notes: # The
+ * HWRM shall allow this command to be requested against any dir_type value (and
+ * not limit it to a subset). # In the case of an updated HWRM firmware, the new
+ * firmware version shall not automatically take effect (i.e. be executed).
+ */
+/* Input (24 bytes) */
+
+struct hwrm_nvm_verify_update_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint16_t dir_type;
+ /* Directory Entry Type, to be verified. */
+ uint16_t dir_ordinal;
+ /* Directory ordinal. The instance of the Directory Type to be verified. */
+ uint16_t dir_ext;
+ /*
+ * The Directory Entry Extension flags. The "UPDATE" extension flag must
+ * be set in this value. A corresponding directory entry with the same
+ * type and ordinal values but *without* the "UPDATE" extension flag
+ * must also exist. The other flags of the extension must be identical
+ * between the active and update entries.
+ */
+ uint16_t unused_0;
+} __attribute__((packed));
+
+/* Output (16 bytes) */
+
+struct hwrm_nvm_verify_update_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint32_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+/* hwrm_nvm_install_update */
+/*
+ * Description: Install a staged NVM package. A package file must first be
+ * staged into the "UPDATE" NVM item. This staging is accomplished using the
+ * nvm_write and/or nvm_modify HWRM commands.
+ */
+/* Input (24 bytes) */
+
+struct hwrm_nvm_install_update_input {
+ uint16_t req_type;
+ /*
+ * This value indicates what type of request this is. The format for the
+ * rest of the command is determined by this field.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * This value indicates the what completion ring the request will be
+ * optionally completed on. If the value is -1, then no CR completion
+ * will be generated. Any other value must be a valid CR ring_id value
+ * for this function.
+ */
+ uint16_t seq_id;
+ /* This value indicates the command sequence number. */
+ uint16_t target_id;
+ /*
+ * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+ * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+ */
+ uint64_t resp_addr;
+ /*
+ * This is the host address where the response will be written when the
+ * request is complete. This area must be 16B aligned and must be
+ * cleared to zero before the request is made.
+ */
+ uint32_t install_type;
+ /*
+ * Installation type. If the value 3 through 0xffff is used, only
+ * packaged items with that type value will be installed and conditional
+ * installation directives for those packaged items will be over-ridden
+ * (i.e. 'create' or 'replace' will be treated as 'install').
+ */
+ /*
+ * Perform a normal package installation. Conditional
+ * installation directives (e.g. 'create' and 'replace') of
+ * packaged items will be followed.
+ */
+ #define HWRM_NVM_INSTALL_UPDATE_INPUT_INSTALL_TYPE_NORMAL UINT32_C(0x0)
+ /*
+ * Install all packaged items regardless of installation
+ * directive (i.e. treat all packaged items as though they have
+ * an installation directive of 'install').
+ */
+ #define HWRM_NVM_INSTALL_UPDATE_INPUT_INSTALL_TYPE_ALL UINT32_C(0xffffffff)
+ uint32_t unused_0;
+} __attribute__((packed));
+
+/* Output (24 bytes) */
+
+struct hwrm_nvm_install_update_output {
+ uint16_t error_code;
+ /*
+ * Pass/Fail or error type Note: receiver to verify the in parameters,
+ * and fail the call with an error when appropriate
+ */
+ uint16_t req_type;
+ /* This field returns the type of original request. */
+ uint16_t seq_id;
+ /* This field provides original sequence number of the command. */
+ uint16_t resp_len;
+ /*
+ * This field is the length of the response in bytes. The last byte of
+ * the response is a valid flag that will read as '1' when the command
+ * has been completely written to memory.
+ */
+ uint64_t installed_items;
+ /*
+ * Bit-mask of successfully installed items. Bit-0 corresponding to the
+ * first packaged item, Bit-1 for the second item, etc. A value of 0
+ * indicates that no items were successfully installed.
+ */
+ uint8_t result;
+ /* result is 8 b */
+ /* There was no problem with the package installation. */
+ #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_RESULT_SUCCESS UINT32_C(0x0)
+ uint8_t problem_item;
+ /* problem_item is 8 b */
+ /* There was no problem with any packaged items. */
+ #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_PROBLEM_ITEM_NONE UINT32_C(0x0)
+ /* There was a problem with the NVM package itself. */
+ #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_PROBLEM_ITEM_PACKAGE UINT32_C(0xff)
+ uint8_t reset_required;
+ /* reset_required is 8 b */
+ /*
+ * No reset is required for installed/updated firmware or
+ * microcode to take effect.
+ */
+ #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_RESET_REQUIRED_NONE UINT32_C(0x0)
+ /*
+ * A PCIe reset (e.g. system reboot) is required for newly
+ * installed/updated firmware or microcode to take effect.
+ */
+ #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_RESET_REQUIRED_PCI UINT32_C(0x1)
+ /*
+ * A controller power reset (e.g. system power-cycle) is
+ * required for newly installed/updated firmware or microcode to
+ * take effect. Some newly installed/updated firmware or
+ * microcode may still take effect upon the next PCIe reset.
+ */
+ #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_RESET_REQUIRED_POWER UINT32_C(0x2)
+ uint8_t unused_0;
+ uint8_t unused_1;
+ uint8_t unused_2;
+ uint8_t unused_3;
+ uint8_t valid;
+ /*
+ * This field is used in Output records to indicate that the output is
+ * completely written to RAM. This field should be read as '1' to
+ * indicate that the output has been completely written. When writing a
+ * command completion or response to an internal processor, the order of
+ * writes has to be such that this field is written last.
+ */
+} __attribute__((packed));
+
+#endif /* _HSI_STRUCT_DEF_EXTERNAL_H_ */
diff --git a/sys/dev/bnxt/if_bnxt.c b/sys/dev/bnxt/if_bnxt.c
new file mode 100644
index 000000000000..2cca3ec6e926
--- /dev/null
+++ b/sys/dev/bnxt/if_bnxt.c
@@ -0,0 +1,2360 @@
+/*-
+ * Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom, All Rights Reserved.
+ * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
+ *
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/endian.h>
+#include <sys/sockio.h>
+#include <sys/priv.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_var.h>
+#include <net/ethernet.h>
+#include <net/iflib.h>
+
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_rss.h"
+
+#include "ifdi_if.h"
+
+#include "bnxt.h"
+#include "bnxt_hwrm.h"
+#include "bnxt_ioctl.h"
+#include "bnxt_sysctl.h"
+#include "hsi_struct_def.h"
+
+/*
+ * PCI Device ID Table
+ */
+
+static pci_vendor_info_t bnxt_vendor_info_array[] =
+{
+ PVID(BROADCOM_VENDOR_ID, BCM57301,
+ "Broadcom BCM57301 NetXtreme-C 10Gb Ethernet Controller"),
+ PVID(BROADCOM_VENDOR_ID, BCM57302,
+ "Broadcom BCM57302 NetXtreme-C 10Gb/25Gb Ethernet Controller"),
+ PVID(BROADCOM_VENDOR_ID, BCM57304,
+ "Broadcom BCM57304 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet Controller"),
+ PVID(BROADCOM_VENDOR_ID, BCM57402,
+ "Broadcom BCM57402 NetXtreme-E 10Gb Ethernet Controller"),
+ PVID(BROADCOM_VENDOR_ID, BCM57404,
+ "Broadcom BCM57404 NetXtreme-E 10Gb/25Gb Ethernet Controller"),
+ PVID(BROADCOM_VENDOR_ID, BCM57406,
+ "Broadcom BCM57406 NetXtreme-E 10GBase-T Ethernet Controller"),
+ PVID(BROADCOM_VENDOR_ID, BCM57402_NPAR,
+ "Broadcom BCM57402 NetXtreme-E Partition"),
+ PVID(BROADCOM_VENDOR_ID, BCM57407,
+ "Broadcom BCM57407 NetXtreme-E 10GBase-T Ethernet Controller"),
+ PVID(BROADCOM_VENDOR_ID, BCM57404_NPAR,
+ "Broadcom BCM57404 NetXtreme-E Partition"),
+ PVID(BROADCOM_VENDOR_ID, BCM57406_NPAR,
+ "Broadcom BCM57406 NetXtreme-E Partition"),
+ PVID(BROADCOM_VENDOR_ID, BCM57407_SFP,
+ "Broadcom BCM57407 NetXtreme-E 25Gb Ethernet Controller"),
+ PVID(BROADCOM_VENDOR_ID, BCM57304_VF,
+ "Broadcom BCM57304 NetXtreme-C Virtual Function"),
+ PVID(BROADCOM_VENDOR_ID, BCM57404_VF,
+ "Broadcom BCM57404 NetXtreme-E Virtual Function"),
+ /* required last entry */
+
+ PVID_END
+};
+
+/*
+ * Function prototypes
+ */
+
+static void *bnxt_register(device_t dev);
+
+/* Soft queue setup and teardown */
+static int bnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
+ uint64_t *paddrs, int ntxqs, int ntxqsets);
+static int bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
+ uint64_t *paddrs, int nrxqs, int nrxqsets);
+static void bnxt_queues_free(if_ctx_t ctx);
+
+/* Device setup and teardown */
+static int bnxt_attach_pre(if_ctx_t ctx);
+static int bnxt_attach_post(if_ctx_t ctx);
+static int bnxt_detach(if_ctx_t ctx);
+
+/* Device configuration */
+static void bnxt_init(if_ctx_t ctx);
+static void bnxt_stop(if_ctx_t ctx);
+static void bnxt_multi_set(if_ctx_t ctx);
+static int bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu);
+static void bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr);
+static int bnxt_media_change(if_ctx_t ctx);
+static int bnxt_promisc_set(if_ctx_t ctx, int flags);
+static uint64_t bnxt_get_counter(if_ctx_t, ift_counter);
+static void bnxt_update_admin_status(if_ctx_t ctx);
+
+/* Interrupt enable / disable */
+static void bnxt_intr_enable(if_ctx_t ctx);
+static int bnxt_queue_intr_enable(if_ctx_t ctx, uint16_t qid);
+static void bnxt_disable_intr(if_ctx_t ctx);
+static int bnxt_msix_intr_assign(if_ctx_t ctx, int msix);
+
+/* vlan support */
+static void bnxt_vlan_register(if_ctx_t ctx, uint16_t vtag);
+static void bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag);
+
+/* ioctl */
+static int bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data);
+
+/* Internal support functions */
+static int bnxt_probe_phy(struct bnxt_softc *softc);
+static void bnxt_add_media_types(struct bnxt_softc *softc);
+static int bnxt_pci_mapping(struct bnxt_softc *softc);
+static void bnxt_pci_mapping_free(struct bnxt_softc *softc);
+static int bnxt_update_link(struct bnxt_softc *softc, bool chng_link_state);
+static int bnxt_handle_def_cp(void *arg);
+static int bnxt_handle_rx_cp(void *arg);
+static void bnxt_clear_ids(struct bnxt_softc *softc);
+static void inline bnxt_do_enable_intr(struct bnxt_cp_ring *cpr);
+static void inline bnxt_do_disable_intr(struct bnxt_cp_ring *cpr);
+static void bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr);
+static void bnxt_def_cp_task(void *context);
+static void bnxt_handle_async_event(struct bnxt_softc *softc,
+ struct cmpl_base *cmpl);
+static uint8_t get_phy_type(struct bnxt_softc *softc);
+static uint64_t bnxt_get_baudrate(struct bnxt_link_info *link);
+
+/*
+ * Device Interface Declaration
+ */
+
+static device_method_t bnxt_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_register, bnxt_register),
+ DEVMETHOD(device_probe, iflib_device_probe),
+ DEVMETHOD(device_attach, iflib_device_attach),
+ DEVMETHOD(device_detach, iflib_device_detach),
+ DEVMETHOD(device_shutdown, iflib_device_shutdown),
+ DEVMETHOD(device_suspend, iflib_device_suspend),
+ DEVMETHOD(device_resume, iflib_device_resume),
+ DEVMETHOD_END
+};
+
+static driver_t bnxt_driver = {
+ "bnxt", bnxt_methods, sizeof(struct bnxt_softc),
+};
+
+devclass_t bnxt_devclass;
+DRIVER_MODULE(bnxt, pci, bnxt_driver, bnxt_devclass, 0, 0);
+
+MODULE_DEPEND(bnxt, pci, 1, 1, 1);
+MODULE_DEPEND(bnxt, ether, 1, 1, 1);
+MODULE_DEPEND(bnxt, iflib, 1, 1, 1);
+
+static device_method_t bnxt_iflib_methods[] = {
+ DEVMETHOD(ifdi_tx_queues_alloc, bnxt_tx_queues_alloc),
+ DEVMETHOD(ifdi_rx_queues_alloc, bnxt_rx_queues_alloc),
+ DEVMETHOD(ifdi_queues_free, bnxt_queues_free),
+
+ DEVMETHOD(ifdi_attach_pre, bnxt_attach_pre),
+ DEVMETHOD(ifdi_attach_post, bnxt_attach_post),
+ DEVMETHOD(ifdi_detach, bnxt_detach),
+
+ DEVMETHOD(ifdi_init, bnxt_init),
+ DEVMETHOD(ifdi_stop, bnxt_stop),
+ DEVMETHOD(ifdi_multi_set, bnxt_multi_set),
+ DEVMETHOD(ifdi_mtu_set, bnxt_mtu_set),
+ DEVMETHOD(ifdi_media_status, bnxt_media_status),
+ DEVMETHOD(ifdi_media_change, bnxt_media_change),
+ DEVMETHOD(ifdi_promisc_set, bnxt_promisc_set),
+ DEVMETHOD(ifdi_get_counter, bnxt_get_counter),
+ DEVMETHOD(ifdi_update_admin_status, bnxt_update_admin_status),
+
+ DEVMETHOD(ifdi_intr_enable, bnxt_intr_enable),
+ DEVMETHOD(ifdi_queue_intr_enable, bnxt_queue_intr_enable),
+ DEVMETHOD(ifdi_intr_disable, bnxt_disable_intr),
+ DEVMETHOD(ifdi_msix_intr_assign, bnxt_msix_intr_assign),
+
+ DEVMETHOD(ifdi_vlan_register, bnxt_vlan_register),
+ DEVMETHOD(ifdi_vlan_unregister, bnxt_vlan_unregister),
+
+ DEVMETHOD(ifdi_priv_ioctl, bnxt_priv_ioctl),
+
+ DEVMETHOD_END
+};
+
+static driver_t bnxt_iflib_driver = {
+ "bnxt", bnxt_iflib_methods, sizeof(struct bnxt_softc)
+};
+
+/*
+ * iflib shared context
+ */
+
+char bnxt_driver_version[] = "https://github.com/Broadcom/freebsd-nxt/commits/bnxt-dev";
+extern struct if_txrx bnxt_txrx;
+static struct if_shared_ctx bnxt_sctx_init = {
+ .isc_magic = IFLIB_MAGIC,
+ .isc_txrx = &bnxt_txrx,
+ .isc_driver = &bnxt_iflib_driver,
+ .isc_nfl = 2, // Number of Free Lists
+ .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ,
+ .isc_q_align = PAGE_SIZE,
+ .isc_tx_maxsize = BNXT_TSO_SIZE,
+ .isc_tx_maxsegsize = BNXT_TSO_SIZE,
+ .isc_rx_maxsize = BNXT_TSO_SIZE,
+ .isc_rx_maxsegsize = BNXT_TSO_SIZE,
+
+ // Only use a single segment to avoid page size constraints
+ .isc_rx_nsegments = 1,
+ .isc_ntxqs = 2,
+ .isc_nrxqs = 3,
+ .isc_nrxd_min = {16, 16, 16},
+ .isc_nrxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 8,
+ PAGE_SIZE / sizeof(struct rx_prod_pkt_bd),
+ PAGE_SIZE / sizeof(struct rx_prod_pkt_bd)},
+ .isc_nrxd_max = {INT32_MAX, INT32_MAX, INT32_MAX},
+ .isc_ntxd_min = {16, 16, 16},
+ .isc_ntxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 2,
+ PAGE_SIZE / sizeof(struct tx_bd_short)},
+ .isc_ntxd_max = {INT32_MAX, INT32_MAX, INT32_MAX},
+
+ .isc_admin_intrcnt = 1,
+ .isc_vendor_info = bnxt_vendor_info_array,
+ .isc_driver_version = bnxt_driver_version,
+};
+
+if_shared_ctx_t bnxt_sctx = &bnxt_sctx_init;
+
+/*
+ * Device Methods
+ */
+
+static void *
+bnxt_register(device_t dev)
+{
+ return bnxt_sctx;
+}
+
+/*
+ * Device Dependent Configuration Functions
+*/
+
+/* Soft queue setup and teardown */
+static int
+bnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
+ uint64_t *paddrs, int ntxqs, int ntxqsets)
+{
+ struct bnxt_softc *softc;
+ int i;
+ int rc;
+
+ softc = iflib_get_softc(ctx);
+
+ softc->tx_cp_rings = malloc(sizeof(struct bnxt_cp_ring) * ntxqsets,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!softc->tx_cp_rings) {
+ device_printf(iflib_get_dev(ctx),
+ "unable to allocate TX completion rings\n");
+ rc = ENOMEM;
+ goto cp_alloc_fail;
+ }
+ softc->tx_rings = malloc(sizeof(struct bnxt_ring) * ntxqsets,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!softc->tx_rings) {
+ device_printf(iflib_get_dev(ctx),
+ "unable to allocate TX rings\n");
+ rc = ENOMEM;
+ goto ring_alloc_fail;
+ }
+ rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * ntxqsets,
+ &softc->tx_stats, 0);
+ if (rc)
+ goto dma_alloc_fail;
+ bus_dmamap_sync(softc->tx_stats.idi_tag, softc->tx_stats.idi_map,
+ BUS_DMASYNC_PREREAD);
+
+ for (i = 0; i < ntxqsets; i++) {
+ /* Set up the completion ring */
+ softc->tx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE;
+ softc->tx_cp_rings[i].ring.phys_id =
+ (uint16_t)HWRM_NA_SIGNATURE;
+ softc->tx_cp_rings[i].ring.softc = softc;
+ softc->tx_cp_rings[i].ring.id =
+ (softc->scctx->isc_nrxqsets * 2) + 1 + i;
+ softc->tx_cp_rings[i].ring.doorbell =
+ softc->tx_cp_rings[i].ring.id * 0x80;
+ softc->tx_cp_rings[i].ring.ring_size =
+ softc->scctx->isc_ntxd[0];
+ softc->tx_cp_rings[i].ring.vaddr = vaddrs[i * ntxqs];
+ softc->tx_cp_rings[i].ring.paddr = paddrs[i * ntxqs];
+
+ /* Set up the TX ring */
+ softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->tx_rings[i].softc = softc;
+ softc->tx_rings[i].id =
+ (softc->scctx->isc_nrxqsets * 2) + 1 + i;
+ softc->tx_rings[i].doorbell = softc->tx_rings[i].id * 0x80;
+ softc->tx_rings[i].ring_size = softc->scctx->isc_ntxd[1];
+ softc->tx_rings[i].vaddr = vaddrs[i * ntxqs + 1];
+ softc->tx_rings[i].paddr = paddrs[i * ntxqs + 1];
+
+ bnxt_create_tx_sysctls(softc, i);
+ }
+
+ softc->ntxqsets = ntxqsets;
+ return rc;
+
+dma_alloc_fail:
+ free(softc->tx_rings, M_DEVBUF);
+ring_alloc_fail:
+ free(softc->tx_cp_rings, M_DEVBUF);
+cp_alloc_fail:
+ return rc;
+}
+
+static void
+bnxt_queues_free(if_ctx_t ctx)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+
+ // Free TX queues
+ iflib_dma_free(&softc->tx_stats);
+ free(softc->tx_rings, M_DEVBUF);
+ softc->tx_rings = NULL;
+ free(softc->tx_cp_rings, M_DEVBUF);
+ softc->tx_cp_rings = NULL;
+ softc->ntxqsets = 0;
+
+ // Free RX queues
+ iflib_dma_free(&softc->rx_stats);
+ free(softc->grp_info, M_DEVBUF);
+ free(softc->ag_rings, M_DEVBUF);
+ free(softc->rx_rings, M_DEVBUF);
+ free(softc->rx_cp_rings, M_DEVBUF);
+}
+
+static int
+bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
+ uint64_t *paddrs, int nrxqs, int nrxqsets)
+{
+ struct bnxt_softc *softc;
+ int i;
+ int rc;
+
+ softc = iflib_get_softc(ctx);
+
+ softc->rx_cp_rings = malloc(sizeof(struct bnxt_cp_ring) * nrxqsets,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!softc->rx_cp_rings) {
+ device_printf(iflib_get_dev(ctx),
+ "unable to allocate RX completion rings\n");
+ rc = ENOMEM;
+ goto cp_alloc_fail;
+ }
+ softc->rx_rings = malloc(sizeof(struct bnxt_ring) * nrxqsets,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!softc->rx_rings) {
+ device_printf(iflib_get_dev(ctx),
+ "unable to allocate RX rings\n");
+ rc = ENOMEM;
+ goto ring_alloc_fail;
+ }
+ softc->ag_rings = malloc(sizeof(struct bnxt_ring) * nrxqsets,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!softc->ag_rings) {
+ device_printf(iflib_get_dev(ctx),
+ "unable to allocate aggregation rings\n");
+ rc = ENOMEM;
+ goto ag_alloc_fail;
+ }
+ softc->grp_info = malloc(sizeof(struct bnxt_grp_info) * nrxqsets,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!softc->grp_info) {
+ device_printf(iflib_get_dev(ctx),
+ "unable to allocate ring groups\n");
+ rc = ENOMEM;
+ goto grp_alloc_fail;
+ }
+
+ rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * nrxqsets,
+ &softc->rx_stats, 0);
+ if (rc)
+ goto hw_stats_alloc_fail;
+ bus_dmamap_sync(softc->rx_stats.idi_tag, softc->rx_stats.idi_map,
+ BUS_DMASYNC_PREREAD);
+
+ for (i = 0; i < nrxqsets; i++) {
+ /* Allocation the completion ring */
+ softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE;
+ softc->rx_cp_rings[i].ring.phys_id =
+ (uint16_t)HWRM_NA_SIGNATURE;
+ softc->rx_cp_rings[i].ring.softc = softc;
+ softc->rx_cp_rings[i].ring.id = i + 1;
+ softc->rx_cp_rings[i].ring.doorbell =
+ softc->rx_cp_rings[i].ring.id * 0x80;
+ /*
+ * If this ring overflows, RX stops working.
+ */
+ softc->rx_cp_rings[i].ring.ring_size =
+ softc->scctx->isc_nrxd[0];
+ softc->rx_cp_rings[i].ring.vaddr = vaddrs[i * nrxqs];
+ softc->rx_cp_rings[i].ring.paddr = paddrs[i * nrxqs];
+
+ /* Allocate the RX ring */
+ softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->rx_rings[i].softc = softc;
+ softc->rx_rings[i].id = i + 1;
+ softc->rx_rings[i].doorbell = softc->rx_rings[i].id * 0x80;
+ softc->rx_rings[i].ring_size = softc->scctx->isc_nrxd[1];
+ softc->rx_rings[i].vaddr = vaddrs[i * nrxqs + 1];
+ softc->rx_rings[i].paddr = paddrs[i * nrxqs + 1];
+
+ /* Allocate the AG ring */
+ softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->ag_rings[i].softc = softc;
+ softc->ag_rings[i].id = nrxqsets + i + 1;
+ softc->ag_rings[i].doorbell = softc->ag_rings[i].id * 0x80;
+ softc->ag_rings[i].ring_size = softc->scctx->isc_nrxd[2];
+ softc->ag_rings[i].vaddr = vaddrs[i * nrxqs + 2];
+ softc->ag_rings[i].paddr = paddrs[i * nrxqs + 2];
+
+ /* Allocate the ring group */
+ softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->grp_info[i].stats_ctx =
+ softc->rx_cp_rings[i].stats_ctx_id;
+ softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id;
+ softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id;
+ softc->grp_info[i].cp_ring_id =
+ softc->rx_cp_rings[i].ring.phys_id;
+
+ bnxt_create_rx_sysctls(softc, i);
+ }
+
+ /* And finally, the VNIC */
+ softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->vnic_info.flow_id = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->vnic_info.filter_id = -1;
+ softc->vnic_info.def_ring_grp = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->vnic_info.cos_rule = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->vnic_info.lb_rule = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->vnic_info.rx_mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST;
+ softc->vnic_info.mc_list_count = 0;
+ softc->vnic_info.flags = BNXT_VNIC_FLAG_DEFAULT;
+ rc = iflib_dma_alloc(ctx, BNXT_MAX_MC_ADDRS * ETHER_ADDR_LEN,
+ &softc->vnic_info.mc_list, 0);
+ if (rc)
+ goto mc_list_alloc_fail;
+
+ /* The VNIC RSS Hash Key */
+ rc = iflib_dma_alloc(ctx, HW_HASH_KEY_SIZE,
+ &softc->vnic_info.rss_hash_key_tbl, 0);
+ if (rc)
+ goto rss_hash_alloc_fail;
+ bus_dmamap_sync(softc->vnic_info.rss_hash_key_tbl.idi_tag,
+ softc->vnic_info.rss_hash_key_tbl.idi_map,
+ BUS_DMASYNC_PREWRITE);
+ memcpy(softc->vnic_info.rss_hash_key_tbl.idi_vaddr,
+ softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE);
+
+ /* Allocate the RSS tables */
+ rc = iflib_dma_alloc(ctx, HW_HASH_INDEX_SIZE * sizeof(uint16_t),
+ &softc->vnic_info.rss_grp_tbl, 0);
+ if (rc)
+ goto rss_grp_alloc_fail;
+ bus_dmamap_sync(softc->vnic_info.rss_grp_tbl.idi_tag,
+ softc->vnic_info.rss_grp_tbl.idi_map,
+ BUS_DMASYNC_PREWRITE);
+ memset(softc->vnic_info.rss_grp_tbl.idi_vaddr, 0xff,
+ softc->vnic_info.rss_grp_tbl.idi_size);
+
+ softc->nrxqsets = nrxqsets;
+ return rc;
+
+rss_grp_alloc_fail:
+ iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl);
+rss_hash_alloc_fail:
+ iflib_dma_free(&softc->vnic_info.mc_list);
+mc_list_alloc_fail:
+ iflib_dma_free(&softc->rx_stats);
+hw_stats_alloc_fail:
+ free(softc->grp_info, M_DEVBUF);
+grp_alloc_fail:
+ free(softc->ag_rings, M_DEVBUF);
+ag_alloc_fail:
+ free(softc->rx_rings, M_DEVBUF);
+ring_alloc_fail:
+ free(softc->rx_cp_rings, M_DEVBUF);
+cp_alloc_fail:
+ return rc;
+}
+
+/* Device setup and teardown */
+static int
+bnxt_attach_pre(if_ctx_t ctx)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ if_softc_ctx_t scctx;
+ int rc = 0;
+
+ softc->ctx = ctx;
+ softc->dev = iflib_get_dev(ctx);
+ softc->media = iflib_get_media(ctx);
+ softc->scctx = iflib_get_softc_ctx(ctx);
+ softc->sctx = iflib_get_sctx(ctx);
+ scctx = softc->scctx;
+
+ switch (softc->sctx->isc_vendor_info->pvi_device_id) {
+ case BCM57402_NPAR:
+ case BCM57404_NPAR:
+ case BCM57406_NPAR:
+ softc->flags |= BNXT_FLAG_NPAR;
+ break;
+ case BCM57304_VF:
+ case BCM57404_VF:
+ softc->flags |= BNXT_FLAG_VF;
+ break;
+ }
+
+ pci_enable_busmaster(softc->dev);
+
+ if (bnxt_pci_mapping(softc))
+ return (ENXIO);
+
+ /* HWRM setup/init */
+ BNXT_HWRM_LOCK_INIT(softc, device_get_nameunit(softc->dev));
+ rc = bnxt_alloc_hwrm_dma_mem(softc);
+ if (rc)
+ goto dma_fail;
+
+ /* Allocate the TPA start buffer */
+ softc->tpa_start = malloc(sizeof(struct bnxt_full_tpa_start) *
+ (RX_TPA_START_CMPL_AGG_ID_MASK >> RX_TPA_START_CMPL_AGG_ID_SFT),
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (softc->tpa_start == NULL) {
+ rc = ENOMEM;
+ device_printf(softc->dev,
+ "Unable to allocate space for TPA\n");
+ goto tpa_failed;
+ }
+
+ /* Get firmware version and compare with driver */
+ softc->ver_info = malloc(sizeof(struct bnxt_ver_info),
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (softc->ver_info == NULL) {
+ rc = ENOMEM;
+ device_printf(softc->dev,
+ "Unable to allocate space for version info\n");
+ goto ver_alloc_fail;
+ }
+ /* Default minimum required HWRM version */
+ softc->ver_info->hwrm_min_major = 1;
+ softc->ver_info->hwrm_min_minor = 2;
+ softc->ver_info->hwrm_min_update = 2;
+
+ rc = bnxt_hwrm_ver_get(softc);
+ if (rc) {
+ device_printf(softc->dev, "attach: hwrm ver get failed\n");
+ goto ver_fail;
+ }
+
+ /* Get NVRAM info */
+ softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info),
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (softc->nvm_info == NULL) {
+ rc = ENOMEM;
+ device_printf(softc->dev,
+ "Unable to allocate space for NVRAM info\n");
+ goto nvm_alloc_fail;
+ }
+ rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id,
+ &softc->nvm_info->device_id, &softc->nvm_info->sector_size,
+ &softc->nvm_info->size, &softc->nvm_info->reserved_size,
+ &softc->nvm_info->available_size);
+
+ /* Register the driver with the FW */
+ rc = bnxt_hwrm_func_drv_rgtr(softc);
+ if (rc) {
+ device_printf(softc->dev, "attach: hwrm drv rgtr failed\n");
+ goto drv_rgtr_fail;
+ }
+
+ /* Get the HW capabilities */
+ rc = bnxt_hwrm_func_qcaps(softc);
+ if (rc)
+ goto failed;
+ iflib_set_mac(ctx, softc->func.mac_addr);
+
+ /* Get the queue config */
+ rc = bnxt_hwrm_queue_qportcfg(softc);
+ if (rc) {
+ device_printf(softc->dev, "attach: hwrm qportcfg failed\n");
+ goto failed;
+ }
+
+ /* Now perform a function reset */
+ rc = bnxt_hwrm_func_reset(softc);
+ bnxt_clear_ids(softc);
+ if (rc)
+ goto failed;
+
+ /* Now set up iflib sc */
+ scctx->isc_tx_nsegments = 31,
+ scctx->isc_tx_tso_segments_max = 31;
+ scctx->isc_tx_tso_size_max = BNXT_TSO_SIZE;
+ scctx->isc_tx_tso_segsize_max = BNXT_TSO_SIZE;
+ scctx->isc_vectors = softc->func.max_cp_rings;
+ if (scctx->isc_nrxd[0] <
+ ((scctx->isc_nrxd[1] * 4) + scctx->isc_nrxd[2]))
+ device_printf(softc->dev,
+ "WARNING: nrxd0 (%d) should be at least 4 * nrxd1 (%d) + nrxd2 (%d). Driver may be unstable\n",
+ scctx->isc_nrxd[0], scctx->isc_nrxd[1], scctx->isc_nrxd[2]);
+ if (scctx->isc_ntxd[0] < scctx->isc_ntxd[1] * 2)
+ device_printf(softc->dev,
+ "WARNING: ntxd0 (%d) should be at least 2 * ntxd1 (%d). Driver may be unstable\n",
+ scctx->isc_ntxd[0], scctx->isc_ntxd[1]);
+ scctx->isc_txqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_ntxd[0];
+ scctx->isc_txqsizes[1] = sizeof(struct tx_bd_short) *
+ scctx->isc_ntxd[1];
+ scctx->isc_rxqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_nrxd[0];
+ scctx->isc_rxqsizes[1] = sizeof(struct rx_prod_pkt_bd) *
+ scctx->isc_nrxd[1];
+ scctx->isc_rxqsizes[2] = sizeof(struct rx_prod_pkt_bd) *
+ scctx->isc_nrxd[2];
+ scctx->isc_max_rxqsets = min(pci_msix_count(softc->dev)-1,
+ softc->func.max_cp_rings - 1);
+ scctx->isc_max_rxqsets = min(scctx->isc_max_rxqsets,
+ softc->func.max_rx_rings);
+ scctx->isc_max_txqsets = min(softc->func.max_rx_rings,
+ softc->func.max_cp_rings - scctx->isc_max_rxqsets - 1);
+ scctx->isc_rss_table_size = HW_HASH_INDEX_SIZE;
+ scctx->isc_rss_table_mask = scctx->isc_rss_table_size - 1;
+
+ /* iflib will map and release this bar */
+ scctx->isc_msix_bar = pci_msix_table_bar(softc->dev);
+
+ /* Allocate the default completion ring */
+ softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE;
+ softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->def_cp_ring.ring.softc = softc;
+ softc->def_cp_ring.ring.id = 0;
+ softc->def_cp_ring.ring.doorbell = softc->def_cp_ring.ring.id * 0x80;
+ softc->def_cp_ring.ring.ring_size = PAGE_SIZE /
+ sizeof(struct cmpl_base);
+ rc = iflib_dma_alloc(ctx,
+ sizeof(struct cmpl_base) * softc->def_cp_ring.ring.ring_size,
+ &softc->def_cp_ring_mem, 0);
+ softc->def_cp_ring.ring.vaddr = softc->def_cp_ring_mem.idi_vaddr;
+ softc->def_cp_ring.ring.paddr = softc->def_cp_ring_mem.idi_paddr;
+ iflib_config_gtask_init(ctx, &softc->def_cp_task, bnxt_def_cp_task,
+ "dflt_cp");
+
+ rc = bnxt_init_sysctl_ctx(softc);
+ if (rc)
+ goto init_sysctl_failed;
+ rc = bnxt_create_nvram_sysctls(softc->nvm_info);
+ if (rc)
+ goto failed;
+
+ arc4rand(softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE, 0);
+ softc->vnic_info.rss_hash_type =
+ HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 |
+ HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4 |
+ HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4 |
+ HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6 |
+ HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6 |
+ HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6;
+ rc = bnxt_create_config_sysctls_pre(softc);
+ if (rc)
+ goto failed;
+
+ /* Initialize the vlan list */
+ SLIST_INIT(&softc->vnic_info.vlan_tags);
+ softc->vnic_info.vlan_tag_list.idi_vaddr = NULL;
+
+ return (rc);
+
+failed:
+ bnxt_free_sysctl_ctx(softc);
+init_sysctl_failed:
+ bnxt_hwrm_func_drv_unrgtr(softc, false);
+drv_rgtr_fail:
+ free(softc->nvm_info, M_DEVBUF);
+nvm_alloc_fail:
+ver_fail:
+ free(softc->ver_info, M_DEVBUF);
+ver_alloc_fail:
+ free(softc->tpa_start, M_DEVBUF);
+tpa_failed:
+ bnxt_free_hwrm_dma_mem(softc);
+dma_fail:
+ BNXT_HWRM_LOCK_DESTROY(softc);
+ bnxt_pci_mapping_free(softc);
+ pci_disable_busmaster(softc->dev);
+ return (rc);
+}
+
+static int
+bnxt_attach_post(if_ctx_t ctx)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ if_t ifp = iflib_get_ifp(ctx);
+ int capabilities, enabling;
+ int rc;
+
+ bnxt_create_config_sysctls_post(softc);
+
+ /* Update link state etc... */
+ rc = bnxt_probe_phy(softc);
+ if (rc)
+ goto failed;
+
+ /* Needs to be done after probing the phy */
+ bnxt_create_ver_sysctls(softc);
+ bnxt_add_media_types(softc);
+ ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO);
+
+ if_sethwassist(ifp, (CSUM_TCP | CSUM_UDP | CSUM_TCP_IPV6 |
+ CSUM_UDP_IPV6 | CSUM_TSO));
+
+ capabilities =
+ /* These are translated to hwassit bits */
+ IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 | IFCAP_TSO4 | IFCAP_TSO6 |
+ /* These are checked by iflib */
+ IFCAP_LRO | IFCAP_VLAN_HWFILTER |
+ /* These are part of the iflib mask */
+ IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_VLAN_MTU |
+ IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO |
+ /* These likely get lost... */
+ IFCAP_VLAN_HWCSUM | IFCAP_JUMBO_MTU;
+
+ if_setcapabilities(ifp, capabilities);
+
+ enabling = capabilities;
+
+ if_setcapenable(ifp, enabling);
+
+ softc->scctx->isc_max_frame_size = ifp->if_mtu + ETHER_HDR_LEN +
+ ETHER_CRC_LEN;
+
+failed:
+ return rc;
+}
+
+static int
+bnxt_detach(if_ctx_t ctx)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ struct bnxt_vlan_tag *tag;
+ struct bnxt_vlan_tag *tmp;
+ int i;
+
+ bnxt_do_disable_intr(&softc->def_cp_ring);
+ bnxt_free_sysctl_ctx(softc);
+ bnxt_hwrm_func_reset(softc);
+ bnxt_clear_ids(softc);
+ iflib_irq_free(ctx, &softc->def_cp_ring.irq);
+ iflib_config_gtask_deinit(&softc->def_cp_task);
+ /* We need to free() these here... */
+ for (i = softc->nrxqsets-1; i>=0; i--) {
+ iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq);
+ }
+ iflib_dma_free(&softc->vnic_info.mc_list);
+ iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl);
+ iflib_dma_free(&softc->vnic_info.rss_grp_tbl);
+ if (softc->vnic_info.vlan_tag_list.idi_vaddr)
+ iflib_dma_free(&softc->vnic_info.vlan_tag_list);
+ SLIST_FOREACH_SAFE(tag, &softc->vnic_info.vlan_tags, next, tmp)
+ free(tag, M_DEVBUF);
+ iflib_dma_free(&softc->def_cp_ring_mem);
+ free(softc->tpa_start, M_DEVBUF);
+ free(softc->ver_info, M_DEVBUF);
+ free(softc->nvm_info, M_DEVBUF);
+
+ bnxt_hwrm_func_drv_unrgtr(softc, false);
+ bnxt_free_hwrm_dma_mem(softc);
+ BNXT_HWRM_LOCK_DESTROY(softc);
+
+ pci_disable_busmaster(softc->dev);
+ bnxt_pci_mapping_free(softc);
+
+ return 0;
+}
+
+/* Device configuration */
+static void
+bnxt_init(if_ctx_t ctx)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ struct ifmediareq ifmr;
+ int i, j;
+ int rc;
+
+ rc = bnxt_hwrm_func_reset(softc);
+ if (rc)
+ return;
+ bnxt_clear_ids(softc);
+
+ /* Allocate the default completion ring */
+ softc->def_cp_ring.cons = UINT32_MAX;
+ softc->def_cp_ring.v_bit = 1;
+ bnxt_mark_cpr_invalid(&softc->def_cp_ring);
+ rc = bnxt_hwrm_ring_alloc(softc,
+ HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL,
+ &softc->def_cp_ring.ring,
+ (uint16_t)HWRM_NA_SIGNATURE,
+ HWRM_NA_SIGNATURE, true);
+ if (rc)
+ goto fail;
+
+ /* And now set the default CP ring as the async CP ring */
+ rc = bnxt_hwrm_func_cfg(softc);
+ if (rc)
+ goto fail;
+
+ for (i = 0; i < softc->nrxqsets; i++) {
+ /* Allocate the statistics context */
+ rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->rx_cp_rings[i],
+ softc->rx_stats.idi_paddr +
+ (sizeof(struct ctx_hw_stats) * i));
+ if (rc)
+ goto fail;
+
+ /* Allocate the completion ring */
+ softc->rx_cp_rings[i].cons = UINT32_MAX;
+ softc->rx_cp_rings[i].v_bit = 1;
+ softc->rx_cp_rings[i].last_idx = UINT32_MAX;
+ bnxt_mark_cpr_invalid(&softc->rx_cp_rings[i]);
+ rc = bnxt_hwrm_ring_alloc(softc,
+ HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL,
+ &softc->rx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE,
+ HWRM_NA_SIGNATURE, true);
+ if (rc)
+ goto fail;
+
+ /* Allocate the RX ring */
+ rc = bnxt_hwrm_ring_alloc(softc,
+ HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
+ &softc->rx_rings[i], (uint16_t)HWRM_NA_SIGNATURE,
+ HWRM_NA_SIGNATURE, false);
+ if (rc)
+ goto fail;
+ BNXT_RX_DB(&softc->rx_rings[i], 0);
+ /* TODO: Cumulus+ doesn't need the double doorbell */
+ BNXT_RX_DB(&softc->rx_rings[i], 0);
+
+ /* Allocate the AG ring */
+ rc = bnxt_hwrm_ring_alloc(softc,
+ HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
+ &softc->ag_rings[i], (uint16_t)HWRM_NA_SIGNATURE,
+ HWRM_NA_SIGNATURE, false);
+ if (rc)
+ goto fail;
+ BNXT_RX_DB(&softc->rx_rings[i], 0);
+ /* TODO: Cumulus+ doesn't need the double doorbell */
+ BNXT_RX_DB(&softc->ag_rings[i], 0);
+
+ /* Allocate the ring group */
+ softc->grp_info[i].stats_ctx =
+ softc->rx_cp_rings[i].stats_ctx_id;
+ softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id;
+ softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id;
+ softc->grp_info[i].cp_ring_id =
+ softc->rx_cp_rings[i].ring.phys_id;
+ rc = bnxt_hwrm_ring_grp_alloc(softc, &softc->grp_info[i]);
+ if (rc)
+ goto fail;
+
+ }
+
+ /* Allocate the VNIC RSS context */
+ rc = bnxt_hwrm_vnic_ctx_alloc(softc, &softc->vnic_info.rss_id);
+ if (rc)
+ goto fail;
+
+ /* Allocate the vnic */
+ softc->vnic_info.def_ring_grp = softc->grp_info[0].grp_id;
+ softc->vnic_info.mru = softc->scctx->isc_max_frame_size;
+ rc = bnxt_hwrm_vnic_alloc(softc, &softc->vnic_info);
+ if (rc)
+ goto fail;
+ rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info);
+ if (rc)
+ goto fail;
+ rc = bnxt_hwrm_set_filter(softc, &softc->vnic_info);
+ if (rc)
+ goto fail;
+
+ /* Enable RSS on the VNICs */
+ for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) {
+ ((uint16_t *)
+ softc->vnic_info.rss_grp_tbl.idi_vaddr)[i] =
+ htole16(softc->grp_info[j].grp_id);
+ if (++j == softc->nrxqsets)
+ j = 0;
+ }
+
+ rc = bnxt_hwrm_rss_cfg(softc, &softc->vnic_info,
+ softc->vnic_info.rss_hash_type);
+ if (rc)
+ goto fail;
+
+#ifdef notyet
+ /* Enable LRO/TPA/GRO */
+ rc = bnxt_hwrm_vnic_tpa_cfg(softc, &softc->vnic_info,
+ (if_getcapenable(iflib_get_ifp(ctx)) & IFCAP_LRO) ?
+ HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA : 0);
+ if (rc)
+ goto fail;
+#endif
+
+ for (i = 0; i < softc->ntxqsets; i++) {
+ /* Allocate the statistics context */
+ rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->tx_cp_rings[i],
+ softc->tx_stats.idi_paddr +
+ (sizeof(struct ctx_hw_stats) * i));
+ if (rc)
+ goto fail;
+
+ /* Allocate the completion ring */
+ softc->tx_cp_rings[i].cons = UINT32_MAX;
+ softc->tx_cp_rings[i].v_bit = 1;
+ bnxt_mark_cpr_invalid(&softc->tx_cp_rings[i]);
+ rc = bnxt_hwrm_ring_alloc(softc,
+ HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL,
+ &softc->tx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE,
+ HWRM_NA_SIGNATURE, false);
+ if (rc)
+ goto fail;
+
+ /* Allocate the TX ring */
+ rc = bnxt_hwrm_ring_alloc(softc,
+ HWRM_RING_ALLOC_INPUT_RING_TYPE_TX,
+ &softc->tx_rings[i], softc->tx_cp_rings[i].ring.phys_id,
+ softc->tx_cp_rings[i].stats_ctx_id, false);
+ if (rc)
+ goto fail;
+ BNXT_TX_DB(&softc->tx_rings[i], 0);
+ /* TODO: Cumulus+ doesn't need the double doorbell */
+ BNXT_TX_DB(&softc->tx_rings[i], 0);
+ }
+
+ bnxt_do_enable_intr(&softc->def_cp_ring);
+ bnxt_media_status(softc->ctx, &ifmr);
+ return;
+
+fail:
+ bnxt_hwrm_func_reset(softc);
+ bnxt_clear_ids(softc);
+ return;
+}
+
+static void
+bnxt_stop(if_ctx_t ctx)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+
+ bnxt_do_disable_intr(&softc->def_cp_ring);
+ bnxt_hwrm_func_reset(softc);
+ bnxt_clear_ids(softc);
+ return;
+}
+
+static void
+bnxt_multi_set(if_ctx_t ctx)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ if_t ifp = iflib_get_ifp(ctx);
+ uint8_t *mta;
+ int cnt, mcnt;
+
+ mcnt = if_multiaddr_count(ifp, -1);
+
+ if (mcnt > BNXT_MAX_MC_ADDRS) {
+ softc->vnic_info.rx_mask |=
+ HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
+ bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info);
+ }
+ else {
+ softc->vnic_info.rx_mask &=
+ ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
+ mta = softc->vnic_info.mc_list.idi_vaddr;
+ bzero(mta, softc->vnic_info.mc_list.idi_size);
+ if_multiaddr_array(ifp, mta, &cnt, mcnt);
+ bus_dmamap_sync(softc->vnic_info.mc_list.idi_tag,
+ softc->vnic_info.mc_list.idi_map, BUS_DMASYNC_PREWRITE);
+ softc->vnic_info.mc_list_count = cnt;
+ softc->vnic_info.rx_mask |=
+ HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_MCAST;
+ if (bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info))
+ device_printf(softc->dev,
+ "set_multi: rx_mask set failed\n");
+ }
+}
+
+static int
+bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+
+ if (mtu > BNXT_MAX_MTU)
+ return EINVAL;
+
+ softc->scctx->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
+ return 0;
+}
+
+static void
+bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ struct bnxt_link_info *link_info = &softc->link_info;
+ uint8_t phy_type = get_phy_type(softc);
+
+ bnxt_update_link(softc, true);
+
+ ifmr->ifm_status = IFM_AVALID;
+ ifmr->ifm_active = IFM_ETHER;
+
+ if (link_info->link_up)
+ ifmr->ifm_status |= IFM_ACTIVE;
+ else
+ ifmr->ifm_status &= ~IFM_ACTIVE;
+
+ if (link_info->duplex == HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL)
+ ifmr->ifm_active |= IFM_FDX;
+ else
+ ifmr->ifm_active |= IFM_HDX;
+
+ switch (link_info->link_speed) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB:
+ ifmr->ifm_active |= IFM_100_T;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB:
+ switch (phy_type) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX:
+ ifmr->ifm_active |= IFM_1000_KX;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET:
+ ifmr->ifm_active |= IFM_1000_T;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY:
+ ifmr->ifm_active |= IFM_1000_SGMII;
+ break;
+ default:
+ ifmr->ifm_active |= IFM_UNKNOWN;
+ break;
+ }
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB:
+ switch (phy_type) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX:
+ ifmr->ifm_active |= IFM_2500_KX;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET:
+ ifmr->ifm_active |= IFM_2500_T;
+ break;
+ default:
+ ifmr->ifm_active |= IFM_UNKNOWN;
+ break;
+ }
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB:
+ switch (phy_type) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
+ ifmr->ifm_active |= IFM_10G_CR1;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
+ ifmr->ifm_active |= IFM_10G_KR;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR:
+ ifmr->ifm_active |= IFM_10G_LR;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
+ ifmr->ifm_active |= IFM_10G_SR;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX:
+ ifmr->ifm_active |= IFM_10G_KX4;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET:
+ ifmr->ifm_active |= IFM_10G_T;
+ break;
+ default:
+ ifmr->ifm_active |= IFM_UNKNOWN;
+ break;
+ }
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB:
+ ifmr->ifm_active |= IFM_20G_KR2;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB:
+ switch (phy_type) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
+ ifmr->ifm_active |= IFM_25G_CR;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
+ ifmr->ifm_active |= IFM_25G_KR;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
+ ifmr->ifm_active |= IFM_25G_SR;
+ break;
+ default:
+ ifmr->ifm_active |= IFM_UNKNOWN;
+ break;
+ }
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB:
+ switch (phy_type) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
+ ifmr->ifm_active |= IFM_40G_CR4;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
+ ifmr->ifm_active |= IFM_40G_KR4;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR:
+ ifmr->ifm_active |= IFM_40G_LR4;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
+ ifmr->ifm_active |= IFM_40G_SR4;
+ break;
+ default:
+ ifmr->ifm_active |= IFM_UNKNOWN;
+ break;
+ }
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB:
+ switch (phy_type) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
+ ifmr->ifm_active |= IFM_50G_CR2;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
+ ifmr->ifm_active |= IFM_50G_KR2;
+ break;
+ default:
+ ifmr->ifm_active |= IFM_UNKNOWN;
+ break;
+ }
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB:
+ switch (phy_type) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
+ ifmr->ifm_active |= IFM_100G_CR4;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
+ ifmr->ifm_active |= IFM_100G_KR4;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR:
+ ifmr->ifm_active |= IFM_100G_LR4;
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
+ ifmr->ifm_active |= IFM_100G_SR4;
+ break;
+ default:
+ ifmr->ifm_active |= IFM_UNKNOWN;
+ break;
+ }
+ default:
+ return;
+ }
+
+ if (link_info->pause == (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX))
+ ifmr->ifm_active |= (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE);
+ else if (link_info->pause == HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
+ ifmr->ifm_active |= IFM_ETH_TXPAUSE;
+ else if (link_info->pause == HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
+ ifmr->ifm_active |= IFM_ETH_RXPAUSE;
+
+ bnxt_report_link(softc);
+ return;
+}
+
+static int
+bnxt_media_change(if_ctx_t ctx)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ struct ifmedia *ifm = iflib_get_media(ctx);
+ struct ifmediareq ifmr;
+ int rc;
+
+ if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
+ return EINVAL;
+
+ switch (IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_100_T:
+ softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
+ softc->link_info.req_link_speed =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100MB;
+ break;
+ case IFM_1000_KX:
+ case IFM_1000_T:
+ case IFM_1000_SGMII:
+ softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
+ softc->link_info.req_link_speed =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_1GB;
+ break;
+ case IFM_2500_KX:
+ case IFM_2500_T:
+ softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
+ softc->link_info.req_link_speed =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_2_5GB;
+ break;
+ case IFM_10G_CR1:
+ case IFM_10G_KR:
+ case IFM_10G_LR:
+ case IFM_10G_SR:
+ case IFM_10G_T:
+ softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
+ softc->link_info.req_link_speed =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10GB;
+ break;
+ case IFM_20G_KR2:
+ softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
+ softc->link_info.req_link_speed =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_20GB;
+ break;
+ case IFM_25G_CR:
+ case IFM_25G_KR:
+ case IFM_25G_SR:
+ softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
+ softc->link_info.req_link_speed =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_25GB;
+ break;
+ case IFM_40G_CR4:
+ case IFM_40G_KR4:
+ case IFM_40G_LR4:
+ case IFM_40G_SR4:
+ softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
+ softc->link_info.req_link_speed =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_40GB;
+ break;
+ case IFM_50G_CR2:
+ case IFM_50G_KR2:
+ softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
+ softc->link_info.req_link_speed =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_50GB;
+ break;
+ case IFM_100G_CR4:
+ case IFM_100G_KR4:
+ case IFM_100G_LR4:
+ case IFM_100G_SR4:
+ softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
+ softc->link_info.req_link_speed =
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100GB;
+ break;
+ default:
+ device_printf(softc->dev,
+ "Unsupported media type! Using auto\n");
+ /* Fall-through */
+ case IFM_AUTO:
+ // Auto
+ softc->link_info.autoneg |= BNXT_AUTONEG_SPEED;
+ break;
+ }
+ rc = bnxt_hwrm_set_link_setting(softc, true, true);
+ bnxt_media_status(softc->ctx, &ifmr);
+ return rc;
+}
+
+static int
+bnxt_promisc_set(if_ctx_t ctx, int flags)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ if_t ifp = iflib_get_ifp(ctx);
+ int rc;
+
+ if (ifp->if_flags & IFF_ALLMULTI ||
+ if_multiaddr_count(ifp, -1) > BNXT_MAX_MC_ADDRS)
+ softc->vnic_info.rx_mask |=
+ HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
+ else
+ softc->vnic_info.rx_mask &=
+ ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
+
+ if (ifp->if_flags & IFF_PROMISC)
+ softc->vnic_info.rx_mask |=
+ HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS |
+ HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN;
+ else
+ softc->vnic_info.rx_mask &=
+ ~(HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS |
+ HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN);
+
+ rc = bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info);
+
+ return rc;
+}
+
+static uint64_t
+bnxt_get_counter(if_ctx_t ctx, ift_counter cnt)
+{
+ if_t ifp = iflib_get_ifp(ctx);
+
+ if (cnt < IFCOUNTERS)
+ return if_get_counter_default(ifp, cnt);
+
+ return 0;
+}
+
+static void
+bnxt_update_admin_status(if_ctx_t ctx)
+{
+ /* TODO: do we need to do anything here? */
+ return;
+}
+
+static void inline
+bnxt_do_enable_intr(struct bnxt_cp_ring *cpr)
+{
+ if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
+ /* First time enabling, do not set index */
+ if (cpr->cons == UINT32_MAX)
+ BNXT_CP_ENABLE_DB(&cpr->ring);
+ else
+ BNXT_CP_IDX_ENABLE_DB(&cpr->ring, cpr->cons);
+ }
+}
+
+static void inline
+bnxt_do_disable_intr(struct bnxt_cp_ring *cpr)
+{
+ if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE)
+ BNXT_CP_DISABLE_DB(&cpr->ring);
+}
+
+/* Enable all interrupts */
+static void
+bnxt_intr_enable(if_ctx_t ctx)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ int i;
+
+ bnxt_do_enable_intr(&softc->def_cp_ring);
+ for (i = 0; i < softc->nrxqsets; i++)
+ bnxt_do_enable_intr(&softc->rx_cp_rings[i]);
+
+ return;
+}
+
+/* Enable interrupt for a single queue */
+static int
+bnxt_queue_intr_enable(if_ctx_t ctx, uint16_t qid)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+
+ bnxt_do_enable_intr(&softc->rx_cp_rings[qid]);
+ return 0;
+}
+
+/* Disable all interrupts */
+static void
+bnxt_disable_intr(if_ctx_t ctx)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ int i;
+
+ /*
+ * NOTE: These TX interrupts should never get enabled, so don't
+ * update the index
+ */
+ for (i = 0; i < softc->ntxqsets; i++)
+ bnxt_do_disable_intr(&softc->tx_cp_rings[i]);
+ for (i = 0; i < softc->nrxqsets; i++)
+ bnxt_do_disable_intr(&softc->rx_cp_rings[i]);
+
+ return;
+}
+
+static int
+bnxt_msix_intr_assign(if_ctx_t ctx, int msix)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ int rc;
+ int i;
+
+ rc = iflib_irq_alloc_generic(ctx, &softc->def_cp_ring.irq,
+ softc->def_cp_ring.ring.id + 1, IFLIB_INTR_ADMIN,
+ bnxt_handle_def_cp, softc, 0, "def_cp");
+ if (rc) {
+ device_printf(iflib_get_dev(ctx),
+ "Failed to register default completion ring handler\n");
+ return rc;
+ }
+
+ for (i=0; i<softc->scctx->isc_nrxqsets; i++) {
+ rc = iflib_irq_alloc_generic(ctx, &softc->rx_cp_rings[i].irq,
+ softc->rx_cp_rings[i].ring.id + 1, IFLIB_INTR_RX,
+ bnxt_handle_rx_cp, &softc->rx_cp_rings[i], i, "rx_cp");
+ if (rc) {
+ device_printf(iflib_get_dev(ctx),
+ "Failed to register RX completion ring handler\n");
+ i--;
+ goto fail;
+ }
+ }
+
+ for (i=0; i<softc->scctx->isc_ntxqsets; i++)
+ iflib_softirq_alloc_generic(ctx, i + 1, IFLIB_INTR_TX, NULL, i,
+ "tx_cp");
+
+ return rc;
+
+fail:
+ for (; i>=0; i--)
+ iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq);
+ iflib_irq_free(ctx, &softc->def_cp_ring.irq);
+ return rc;
+}
+
+/*
+ * We're explicitly allowing duplicates here. They will need to be
+ * removed as many times as they are added.
+ */
+static void
+bnxt_vlan_register(if_ctx_t ctx, uint16_t vtag)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ struct bnxt_vlan_tag *new_tag;
+
+ new_tag = malloc(sizeof(struct bnxt_vlan_tag), M_DEVBUF, M_NOWAIT);
+ if (new_tag == NULL)
+ return;
+ new_tag->tag = vtag;
+ new_tag->tpid = 8100;
+ SLIST_INSERT_HEAD(&softc->vnic_info.vlan_tags, new_tag, next);
+};
+
+static void
+bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ struct bnxt_vlan_tag *vlan_tag;
+
+ SLIST_FOREACH(vlan_tag, &softc->vnic_info.vlan_tags, next) {
+ if (vlan_tag->tag == vtag) {
+ SLIST_REMOVE(&softc->vnic_info.vlan_tags, vlan_tag,
+ bnxt_vlan_tag, next);
+ free(vlan_tag, M_DEVBUF);
+ break;
+ }
+ }
+}
+
+static int
+bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
+{
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct ifreq_buffer *ifbuf = &ifr->ifr_ifru.ifru_buffer;
+ struct bnxt_ioctl_header *ioh =
+ (struct bnxt_ioctl_header *)(ifbuf->buffer);
+ int rc = ENOTSUP;
+ struct bnxt_ioctl_data *iod = NULL;
+
+ switch (command) {
+ case SIOCGPRIVATE_0:
+ if ((rc = priv_check(curthread, PRIV_DRIVER)) != 0)
+ goto exit;
+
+ iod = malloc(ifbuf->length, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!iod) {
+ rc = ENOMEM;
+ goto exit;
+ }
+ copyin(ioh, iod, ifbuf->length);
+
+ switch (ioh->type) {
+ case BNXT_HWRM_NVM_FIND_DIR_ENTRY:
+ {
+ struct bnxt_ioctl_hwrm_nvm_find_dir_entry *find =
+ &iod->find;
+
+ rc = bnxt_hwrm_nvm_find_dir_entry(softc, find->type,
+ &find->ordinal, find->ext, &find->index,
+ find->use_index, find->search_opt,
+ &find->data_length, &find->item_length,
+ &find->fw_ver);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_NVM_READ:
+ {
+ struct bnxt_ioctl_hwrm_nvm_read *rd = &iod->read;
+ struct iflib_dma_info dma_data;
+ size_t offset;
+ size_t remain;
+ size_t csize;
+
+ /*
+ * Some HWRM versions can't read more than 0x8000 bytes
+ */
+ rc = iflib_dma_alloc(softc->ctx,
+ min(rd->length, 0x8000), &dma_data, BUS_DMA_NOWAIT);
+ if (rc)
+ break;
+ for (remain = rd->length, offset = 0;
+ remain && offset < rd->length; offset += 0x8000) {
+ csize = min(remain, 0x8000);
+ rc = bnxt_hwrm_nvm_read(softc, rd->index,
+ rd->offset + offset, csize, &dma_data);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ break;
+ }
+ else {
+ copyout(dma_data.idi_vaddr,
+ rd->data + offset, csize);
+ iod->hdr.rc = 0;
+ }
+ remain -= csize;
+ }
+ if (iod->hdr.rc == 0)
+ copyout(iod, ioh, ifbuf->length);
+
+ iflib_dma_free(&dma_data);
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_FW_RESET:
+ {
+ struct bnxt_ioctl_hwrm_fw_reset *rst =
+ &iod->reset;
+
+ rc = bnxt_hwrm_fw_reset(softc, rst->processor,
+ &rst->selfreset);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_FW_QSTATUS:
+ {
+ struct bnxt_ioctl_hwrm_fw_qstatus *qstat =
+ &iod->status;
+
+ rc = bnxt_hwrm_fw_qstatus(softc, qstat->processor,
+ &qstat->selfreset);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_NVM_WRITE:
+ {
+ struct bnxt_ioctl_hwrm_nvm_write *wr =
+ &iod->write;
+
+ rc = bnxt_hwrm_nvm_write(softc, wr->data, true,
+ wr->type, wr->ordinal, wr->ext, wr->attr,
+ wr->option, wr->data_length, wr->keep,
+ &wr->item_length, &wr->index);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_NVM_ERASE_DIR_ENTRY:
+ {
+ struct bnxt_ioctl_hwrm_nvm_erase_dir_entry *erase =
+ &iod->erase;
+
+ rc = bnxt_hwrm_nvm_erase_dir_entry(softc, erase->index);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_NVM_GET_DIR_INFO:
+ {
+ struct bnxt_ioctl_hwrm_nvm_get_dir_info *info =
+ &iod->dir_info;
+
+ rc = bnxt_hwrm_nvm_get_dir_info(softc, &info->entries,
+ &info->entry_length);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_NVM_GET_DIR_ENTRIES:
+ {
+ struct bnxt_ioctl_hwrm_nvm_get_dir_entries *get =
+ &iod->dir_entries;
+ struct iflib_dma_info dma_data;
+
+ rc = iflib_dma_alloc(softc->ctx, get->max_size,
+ &dma_data, BUS_DMA_NOWAIT);
+ if (rc)
+ break;
+ rc = bnxt_hwrm_nvm_get_dir_entries(softc, &get->entries,
+ &get->entry_length, &dma_data);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ copyout(dma_data.idi_vaddr, get->data,
+ get->entry_length * get->entries);
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+ iflib_dma_free(&dma_data);
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_NVM_VERIFY_UPDATE:
+ {
+ struct bnxt_ioctl_hwrm_nvm_verify_update *vrfy =
+ &iod->verify;
+
+ rc = bnxt_hwrm_nvm_verify_update(softc, vrfy->type,
+ vrfy->ordinal, vrfy->ext);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_NVM_INSTALL_UPDATE:
+ {
+ struct bnxt_ioctl_hwrm_nvm_install_update *inst =
+ &iod->install;
+
+ rc = bnxt_hwrm_nvm_install_update(softc,
+ inst->install_type, &inst->installed_items,
+ &inst->result, &inst->problem_item,
+ &inst->reset_required);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_NVM_MODIFY:
+ {
+ struct bnxt_ioctl_hwrm_nvm_modify *mod = &iod->modify;
+
+ rc = bnxt_hwrm_nvm_modify(softc, mod->index,
+ mod->offset, mod->data, true, mod->length);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_FW_GET_TIME:
+ {
+ struct bnxt_ioctl_hwrm_fw_get_time *gtm =
+ &iod->get_time;
+
+ rc = bnxt_hwrm_fw_get_time(softc, &gtm->year,
+ &gtm->month, &gtm->day, &gtm->hour, &gtm->minute,
+ &gtm->second, &gtm->millisecond, &gtm->zone);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ case BNXT_HWRM_FW_SET_TIME:
+ {
+ struct bnxt_ioctl_hwrm_fw_set_time *stm =
+ &iod->set_time;
+
+ rc = bnxt_hwrm_fw_set_time(softc, stm->year,
+ stm->month, stm->day, stm->hour, stm->minute,
+ stm->second, stm->millisecond, stm->zone);
+ if (rc) {
+ iod->hdr.rc = rc;
+ copyout(&iod->hdr.rc, &ioh->rc,
+ sizeof(ioh->rc));
+ }
+ else {
+ iod->hdr.rc = 0;
+ copyout(iod, ioh, ifbuf->length);
+ }
+
+ rc = 0;
+ goto exit;
+ }
+ }
+ break;
+ }
+
+exit:
+ if (iod)
+ free(iod, M_DEVBUF);
+ return rc;
+}
+
+/*
+ * Support functions
+ */
+static int
+bnxt_probe_phy(struct bnxt_softc *softc)
+{
+ struct bnxt_link_info *link_info = &softc->link_info;
+ int rc = 0;
+
+ rc = bnxt_update_link(softc, false);
+ if (rc) {
+ device_printf(softc->dev,
+ "Probe phy can't update link (rc: %x)\n", rc);
+ return (rc);
+ }
+
+ /*initialize the ethool setting copy with NVM settings */
+ if (link_info->auto_mode != HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE)
+ link_info->autoneg |= BNXT_AUTONEG_SPEED;
+
+ if (link_info->auto_pause & (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) {
+ if (link_info->auto_pause == (
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX))
+ link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+ link_info->req_flow_ctrl = link_info->auto_pause;
+ } else if (link_info->force_pause & (
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) {
+ link_info->req_flow_ctrl = link_info->force_pause;
+ }
+ link_info->req_duplex = link_info->duplex_setting;
+ if (link_info->autoneg & BNXT_AUTONEG_SPEED)
+ link_info->req_link_speed = link_info->auto_link_speed;
+ else
+ link_info->req_link_speed = link_info->force_link_speed;
+ return (rc);
+}
+
+static void
+bnxt_add_media_types(struct bnxt_softc *softc)
+{
+ struct bnxt_link_info *link_info = &softc->link_info;
+ uint16_t supported;
+ uint8_t phy_type = get_phy_type(softc);
+
+ supported = link_info->support_speeds;
+
+ /* Auto is always supported */
+ ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
+
+ if (softc->flags & BNXT_FLAG_NPAR)
+ return;
+
+ switch (phy_type) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_100G_CR4, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_50G_CR2, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_40G_CR4, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_25G_CR, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_10G_CR1, 0,
+ NULL);
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN:
+ /* Auto only */
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_100G_KR4, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_50G_KR2, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_40G_KR4, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_25G_KR, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_20G_KR2, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_10G_KR, 0,
+ NULL);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR:
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_100G_LR4, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_40G_LR4, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_10G_LR, 0,
+ NULL);
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_100G_SR4, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_40G_SR4, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_25G_SR, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_10G_SR, 0,
+ NULL);
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX:
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_10G_KX4, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_2500_KX, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_1000_KX, 0,
+ NULL);
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET:
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE:
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10MB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_10_T, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_100_T, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_1000_T, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_2500_T, 0,
+ NULL);
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_10G_T, 0,
+ NULL);
+ break;
+ case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY:
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB)
+ ifmedia_add(softc->media, IFM_ETHER | IFM_1000_SGMII, 0,
+ NULL);
+ break;
+ }
+
+ return;
+}
+
+static int
+bnxt_map_bar(struct bnxt_softc *softc, struct bnxt_bar_info *bar, int bar_num, bool shareable)
+{
+ uint32_t flag;
+
+ if (bar->res != NULL) {
+ device_printf(softc->dev, "Bar %d already mapped\n", bar_num);
+ return EDOOFUS;
+ }
+
+ bar->rid = PCIR_BAR(bar_num);
+ flag = RF_ACTIVE;
+ if (shareable)
+ flag |= RF_SHAREABLE;
+
+ if ((bar->res =
+ bus_alloc_resource_any(softc->dev,
+ SYS_RES_MEMORY,
+ &bar->rid,
+ flag)) == NULL) {
+ device_printf(softc->dev,
+ "PCI BAR%d mapping failure\n", bar_num);
+ return (ENXIO);
+ }
+ bar->tag = rman_get_bustag(bar->res);
+ bar->handle = rman_get_bushandle(bar->res);
+ bar->size = rman_get_size(bar->res);
+
+ return 0;
+}
+
+static int
+bnxt_pci_mapping(struct bnxt_softc *softc)
+{
+ int rc;
+
+ rc = bnxt_map_bar(softc, &softc->hwrm_bar, 0, true);
+ if (rc)
+ return rc;
+
+ rc = bnxt_map_bar(softc, &softc->doorbell_bar, 2, false);
+
+ return rc;
+}
+
+static void
+bnxt_pci_mapping_free(struct bnxt_softc *softc)
+{
+ if (softc->hwrm_bar.res != NULL)
+ bus_release_resource(softc->dev, SYS_RES_MEMORY,
+ softc->hwrm_bar.rid, softc->hwrm_bar.res);
+ softc->hwrm_bar.res = NULL;
+
+ if (softc->doorbell_bar.res != NULL)
+ bus_release_resource(softc->dev, SYS_RES_MEMORY,
+ softc->doorbell_bar.rid, softc->doorbell_bar.res);
+ softc->doorbell_bar.res = NULL;
+}
+
+static int
+bnxt_update_link(struct bnxt_softc *softc, bool chng_link_state)
+{
+ struct bnxt_link_info *link_info = &softc->link_info;
+ uint8_t link_up = link_info->link_up;
+ int rc = 0;
+
+ rc = bnxt_hwrm_port_phy_qcfg(softc);
+ if (rc)
+ goto exit;
+
+ /* TODO: need to add more logic to report VF link */
+ if (chng_link_state) {
+ if (link_info->phy_link_status ==
+ HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
+ link_info->link_up = 1;
+ else
+ link_info->link_up = 0;
+ if (link_up != link_info->link_up)
+ bnxt_report_link(softc);
+ } else {
+ /* always link down if not require to update link state */
+ link_info->link_up = 0;
+ }
+
+exit:
+ return rc;
+}
+
+void
+bnxt_report_link(struct bnxt_softc *softc)
+{
+ const char *duplex = NULL, *flow_ctrl = NULL;
+
+ if (softc->link_info.link_up == softc->link_info.last_link_up) {
+ if (!softc->link_info.link_up)
+ return;
+ if (softc->link_info.pause == softc->link_info.last_pause &&
+ softc->link_info.duplex == softc->link_info.last_duplex)
+ return;
+ }
+
+ if (softc->link_info.link_up) {
+ if (softc->link_info.duplex ==
+ HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL)
+ duplex = "full duplex";
+ else
+ duplex = "half duplex";
+ if (softc->link_info.pause == (
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX))
+ flow_ctrl = "FC - receive & transmit";
+ else if (softc->link_info.pause ==
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
+ flow_ctrl = "FC - transmit";
+ else if (softc->link_info.pause ==
+ HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
+ flow_ctrl = "FC - receive";
+ else
+ flow_ctrl = "none";
+ iflib_link_state_change(softc->ctx, LINK_STATE_UP,
+ IF_Gbps(100));
+ device_printf(softc->dev, "Link is UP %s, %s\n", duplex,
+ flow_ctrl);
+ } else {
+ iflib_link_state_change(softc->ctx, LINK_STATE_DOWN,
+ bnxt_get_baudrate(&softc->link_info));
+ device_printf(softc->dev, "Link is Down\n");
+ }
+
+ softc->link_info.last_link_up = softc->link_info.link_up;
+ softc->link_info.last_pause = softc->link_info.pause;
+ softc->link_info.last_duplex = softc->link_info.duplex;
+}
+
+static int
+bnxt_handle_rx_cp(void *arg)
+{
+ struct bnxt_cp_ring *cpr = arg;
+
+ /* Disable further interrupts for this queue */
+ BNXT_CP_DISABLE_DB(&cpr->ring);
+ return FILTER_SCHEDULE_THREAD;
+}
+
+static int
+bnxt_handle_def_cp(void *arg)
+{
+ struct bnxt_softc *softc = arg;
+
+ BNXT_CP_DISABLE_DB(&softc->def_cp_ring.ring);
+ GROUPTASK_ENQUEUE(&softc->def_cp_task);
+ return FILTER_HANDLED;
+}
+
+static void
+bnxt_clear_ids(struct bnxt_softc *softc)
+{
+ int i;
+
+ softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE;
+ softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE;
+ for (i = 0; i < softc->ntxqsets; i++) {
+ softc->tx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE;
+ softc->tx_cp_rings[i].ring.phys_id =
+ (uint16_t)HWRM_NA_SIGNATURE;
+ softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
+ }
+ for (i = 0; i < softc->nrxqsets; i++) {
+ softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE;
+ softc->rx_cp_rings[i].ring.phys_id =
+ (uint16_t)HWRM_NA_SIGNATURE;
+ softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE;
+ }
+ softc->vnic_info.filter_id = -1;
+ softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE;
+ softc->vnic_info.rss_id = (uint16_t)HWRM_NA_SIGNATURE;
+ memset(softc->vnic_info.rss_grp_tbl.idi_vaddr, 0xff,
+ softc->vnic_info.rss_grp_tbl.idi_size);
+}
+
+static void
+bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr)
+{
+ struct cmpl_base *cmp = (void *)cpr->ring.vaddr;
+ int i;
+
+ for (i = 0; i < cpr->ring.ring_size; i++)
+ cmp[i].info3_v = !cpr->v_bit;
+}
+
+static void
+bnxt_handle_async_event(struct bnxt_softc *softc, struct cmpl_base *cmpl)
+{
+ struct hwrm_async_event_cmpl *ae = (void *)cmpl;
+ uint16_t async_id = le16toh(ae->event_id);
+ struct ifmediareq ifmr;
+
+ switch (async_id) {
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE:
+ bnxt_media_status(softc->ctx, &ifmr);
+ break;
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE:
+ case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR:
+ device_printf(softc->dev,
+ "Unhandled async completion type %u\n", async_id);
+ break;
+ default:
+ device_printf(softc->dev,
+ "Unknown async completion type %u\n", async_id);
+ break;
+ }
+}
+
+static void
+bnxt_def_cp_task(void *context)
+{
+ if_ctx_t ctx = context;
+ struct bnxt_softc *softc = iflib_get_softc(ctx);
+ struct bnxt_cp_ring *cpr = &softc->def_cp_ring;
+
+ /* Handle completions on the default completion ring */
+ struct cmpl_base *cmpl;
+ uint32_t cons = cpr->cons;
+ bool v_bit = cpr->v_bit;
+ bool last_v_bit;
+ uint32_t last_cons;
+ uint16_t type;
+
+ for (;;) {
+ last_cons = cons;
+ last_v_bit = v_bit;
+ NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
+ cmpl = &((struct cmpl_base *)cpr->ring.vaddr)[cons];
+
+ if (!CMP_VALID(cmpl, v_bit))
+ break;
+
+ type = le16toh(cmpl->type) & CMPL_BASE_TYPE_MASK;
+ switch (type) {
+ case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT:
+ bnxt_handle_async_event(softc, cmpl);
+ break;
+ case CMPL_BASE_TYPE_TX_L2:
+ case CMPL_BASE_TYPE_RX_L2:
+ case CMPL_BASE_TYPE_RX_AGG:
+ case CMPL_BASE_TYPE_RX_TPA_START:
+ case CMPL_BASE_TYPE_RX_TPA_END:
+ case CMPL_BASE_TYPE_STAT_EJECT:
+ case CMPL_BASE_TYPE_HWRM_DONE:
+ case CMPL_BASE_TYPE_HWRM_FWD_REQ:
+ case CMPL_BASE_TYPE_HWRM_FWD_RESP:
+ case CMPL_BASE_TYPE_CQ_NOTIFICATION:
+ case CMPL_BASE_TYPE_SRQ_EVENT:
+ case CMPL_BASE_TYPE_DBQ_EVENT:
+ case CMPL_BASE_TYPE_QP_EVENT:
+ case CMPL_BASE_TYPE_FUNC_EVENT:
+ device_printf(softc->dev,
+ "Unhandled completion type %u\n", type);
+ break;
+ default:
+ device_printf(softc->dev,
+ "Unknown completion type %u\n", type);
+ break;
+ }
+ }
+
+ cpr->cons = last_cons;
+ cpr->v_bit = last_v_bit;
+ BNXT_CP_IDX_ENABLE_DB(&cpr->ring, cpr->cons);
+}
+
+static uint8_t
+get_phy_type(struct bnxt_softc *softc)
+{
+ struct bnxt_link_info *link_info = &softc->link_info;
+ uint8_t phy_type = link_info->phy_type;
+ uint16_t supported;
+
+ if (phy_type != HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN)
+ return phy_type;
+
+ /* Deduce the phy type from the media type and supported speeds */
+ supported = link_info->support_speeds;
+
+ if (link_info->media_type ==
+ HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_TP)
+ return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET;
+ if (link_info->media_type ==
+ HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_DAC) {
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB)
+ return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX;
+ if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB)
+ return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR;
+ return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR;
+ }
+ if (link_info->media_type ==
+ HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_FIBRE)
+ return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR;
+
+ return phy_type;
+}
+
+bool
+bnxt_check_hwrm_version(struct bnxt_softc *softc)
+{
+ char buf[16];
+
+ sprintf(buf, "%hhu.%hhu.%hhu", softc->ver_info->hwrm_min_major,
+ softc->ver_info->hwrm_min_minor, softc->ver_info->hwrm_min_update);
+ if (softc->ver_info->hwrm_min_major > softc->ver_info->hwrm_if_major) {
+ device_printf(softc->dev,
+ "WARNING: HWRM version %s is too old (older than %s)\n",
+ softc->ver_info->hwrm_if_ver, buf);
+ return false;
+ }
+ else if(softc->ver_info->hwrm_min_major ==
+ softc->ver_info->hwrm_if_major) {
+ if (softc->ver_info->hwrm_min_minor >
+ softc->ver_info->hwrm_if_minor) {
+ device_printf(softc->dev,
+ "WARNING: HWRM version %s is too old (older than %s)\n",
+ softc->ver_info->hwrm_if_ver, buf);
+ return false;
+ }
+ else if (softc->ver_info->hwrm_min_minor ==
+ softc->ver_info->hwrm_if_minor) {
+ if (softc->ver_info->hwrm_min_update >
+ softc->ver_info->hwrm_if_update) {
+ device_printf(softc->dev,
+ "WARNING: HWRM version %s is too old (older than %s)\n",
+ softc->ver_info->hwrm_if_ver, buf);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+static uint64_t
+bnxt_get_baudrate(struct bnxt_link_info *link)
+{
+ switch (link->link_speed) {
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB:
+ return IF_Mbps(100);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB:
+ return IF_Gbps(1);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB:
+ return IF_Gbps(2);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB:
+ return IF_Mbps(2500);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB:
+ return IF_Gbps(10);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB:
+ return IF_Gbps(20);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB:
+ return IF_Gbps(25);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB:
+ return IF_Gbps(40);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB:
+ return IF_Gbps(50);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB:
+ return IF_Gbps(100);
+ case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB:
+ return IF_Mbps(10);
+ }
+ return IF_Gbps(100);
+}
diff --git a/sys/dev/cpuctl/cpuctl.c b/sys/dev/cpuctl/cpuctl.c
index d801f17cd057..e0c0bf75d4ea 100644
--- a/sys/dev/cpuctl/cpuctl.c
+++ b/sys/dev/cpuctl/cpuctl.c
@@ -63,7 +63,7 @@ static d_ioctl_t cpuctl_ioctl;
# define DPRINTF(...)
#endif
-#define UCODE_SIZE_MAX (32 * 1024)
+#define UCODE_SIZE_MAX (4 * 1024 * 1024)
static int cpuctl_do_msr(int cpu, cpuctl_msr_args_t *data, u_long cmd,
struct thread *td);
diff --git a/sys/dev/dme/if_dme.c b/sys/dev/dme/if_dme.c
new file mode 100644
index 000000000000..b18b97753d10
--- /dev/null
+++ b/sys/dev/dme/if_dme.c
@@ -0,0 +1,1061 @@
+/*
+ * Copyright (C) 2015 Alexander Kabaev
+ * Copyright (C) 2010 Andrew Turner
+ * 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.
+ */
+
+/* A driver for the Davicom DM9000 MAC. */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/ethernet.h>
+#include <net/bpf.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/dme/if_dmereg.h>
+#include <dev/dme/if_dmevar.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/extres/regulator/regulator.h>
+#include <dev/gpio/gpiobusvar.h>
+
+#include "miibus_if.h"
+
+struct dme_softc {
+ struct ifnet *dme_ifp;
+ device_t dme_dev;
+ device_t dme_miibus;
+ bus_space_handle_t dme_handle;
+ bus_space_tag_t dme_tag;
+ int dme_rev;
+ int dme_bits;
+ struct resource *dme_res;
+ struct resource *dme_irq;
+ void *dme_intrhand;
+ struct mtx dme_mtx;
+ struct callout dme_tick_ch;
+ struct gpiobus_pin *gpio_rset;
+ uint32_t dme_ticks;
+ uint8_t dme_macaddr[ETHER_ADDR_LEN];
+ regulator_t dme_vcc_regulator;
+ uint8_t dme_txbusy: 1;
+ uint8_t dme_txready: 1;
+ uint16_t dme_txlen;
+};
+
+#define DME_CHIP_DM9000 0x00
+#define DME_CHIP_DM9000A 0x19
+#define DME_CHIP_DM9000B 0x1a
+
+#define DME_INT_PHY 1
+
+static int dme_probe(device_t);
+static int dme_attach(device_t);
+static int dme_detach(device_t);
+
+static void dme_intr(void *arg);
+static void dme_init_locked(struct dme_softc *);
+
+static void dme_prepare(struct dme_softc *);
+static void dme_transmit(struct dme_softc *);
+
+static int dme_miibus_writereg(device_t dev, int phy, int reg, int data);
+static int dme_miibus_readreg(device_t dev, int phy, int reg);
+
+/* The bit on the address bus attached to the CMD pin */
+#define BASE_ADDR 0x000
+#define CMD_ADDR BASE_ADDR
+#define DATA_BIT 1
+#define DATA_ADDR 0x002
+
+#undef DME_TRACE
+
+#ifdef DME_TRACE
+#define DTR3 TR3
+#define DTR4 TR4
+#else
+#define NOTR(args...) (void)0
+#define DTR3 NOTR
+#define DTR4 NOTR
+#endif
+
+static uint8_t
+dme_read_reg(struct dme_softc *sc, uint8_t reg)
+{
+
+ /* Send the register to read from */
+ bus_space_write_1(sc->dme_tag, sc->dme_handle, CMD_ADDR, reg);
+ bus_space_barrier(sc->dme_tag, sc->dme_handle, CMD_ADDR, 1,
+ BUS_SPACE_BARRIER_WRITE);
+
+ /* Get the value of the register */
+ return bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR);
+}
+
+static void
+dme_write_reg(struct dme_softc *sc, uint8_t reg, uint8_t value)
+{
+
+ /* Send the register to write to */
+ bus_space_write_1(sc->dme_tag, sc->dme_handle, CMD_ADDR, reg);
+ bus_space_barrier(sc->dme_tag, sc->dme_handle, CMD_ADDR, 1,
+ BUS_SPACE_BARRIER_WRITE);
+
+ /* Write the value to the register */
+ bus_space_write_1(sc->dme_tag, sc->dme_handle, DATA_ADDR, value);
+ bus_space_barrier(sc->dme_tag, sc->dme_handle, DATA_ADDR, 1,
+ BUS_SPACE_BARRIER_WRITE);
+}
+
+static void
+dme_reset(struct dme_softc *sc)
+{
+ u_int ncr;
+
+ /* Send a soft reset #1 */
+ dme_write_reg(sc, DME_NCR, NCR_RST | NCR_LBK_MAC);
+ DELAY(100); /* Wait for the MAC to reset */
+ ncr = dme_read_reg(sc, DME_NCR);
+ if (ncr & NCR_RST)
+ device_printf(sc->dme_dev, "device did not complete first reset\n");
+
+ /* Send a soft reset #2 per Application Notes v1.22 */
+ dme_write_reg(sc, DME_NCR, 0);
+ dme_write_reg(sc, DME_NCR, NCR_RST | NCR_LBK_MAC);
+ DELAY(100); /* Wait for the MAC to reset */
+ ncr = dme_read_reg(sc, DME_NCR);
+ if (ncr & NCR_RST)
+ device_printf(sc->dme_dev, "device did not complete second reset\n");
+
+ /* Reset trasmit state */
+ sc->dme_txbusy = 0;
+ sc->dme_txready = 0;
+
+ DTR3("dme_reset, flags %#x busy %d ready %d",
+ sc->dme_ifp ? sc->dme_ifp->if_drv_flags : 0,
+ sc->dme_txbusy, sc->dme_txready);
+}
+
+/*
+ * Parse string MAC address into usable form
+ */
+static int
+dme_parse_macaddr(const char *str, uint8_t *mac)
+{
+ int count, i;
+ unsigned int amac[ETHER_ADDR_LEN]; /* Aligned version */
+
+ count = sscanf(str, "%x%*c%x%*c%x%*c%x%*c%x%*c%x",
+ &amac[0], &amac[1], &amac[2],
+ &amac[3], &amac[4], &amac[5]);
+ if (count < ETHER_ADDR_LEN) {
+ memset(mac, 0, ETHER_ADDR_LEN);
+ return (1);
+ }
+
+ /* Copy aligned to result */
+ for (i = 0; i < ETHER_ADDR_LEN; i ++)
+ mac[i] = (amac[i] & 0xff);
+
+ return (0);
+}
+
+/*
+ * Try to determine our own MAC address
+ */
+static void
+dme_get_macaddr(struct dme_softc *sc)
+{
+ char devid_str[32];
+ char *var;
+ int i;
+
+ /* Cannot use resource_string_value with static hints mode */
+ snprintf(devid_str, 32, "hint.%s.%d.macaddr",
+ device_get_name(sc->dme_dev),
+ device_get_unit(sc->dme_dev));
+
+ /* Try resource hints */
+ if ((var = kern_getenv(devid_str)) != NULL) {
+ if (!dme_parse_macaddr(var, sc->dme_macaddr)) {
+ device_printf(sc->dme_dev, "MAC address: %s (hints)\n", var);
+ return;
+ }
+ }
+
+ /*
+ * Try to read MAC address from the device, in case U-Boot has
+ * pre-programmed one for us.
+ */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ sc->dme_macaddr[i] = dme_read_reg(sc, DME_PAR(i));
+
+ device_printf(sc->dme_dev, "MAC address %6D (existing)\n",
+ sc->dme_macaddr, ":");
+}
+
+static void
+dme_config(struct dme_softc *sc)
+{
+ int i;
+
+ /* Mask all interrupts and reset receive pointer */
+ dme_write_reg(sc, DME_IMR, IMR_PAR);
+
+ /* Disable GPIO0 to enable the internal PHY */
+ dme_write_reg(sc, DME_GPCR, 1);
+ dme_write_reg(sc, DME_GPR, 0);
+
+#if 0
+ /*
+ * Supposedly requires special initialization for DSP PHYs
+ * used by DM9000B. Maybe belongs in dedicated PHY driver?
+ */
+ if (sc->dme_rev == DME_CHIP_DM9000B) {
+ dme_miibus_writereg(sc->dme_dev, DME_INT_PHY, MII_BMCR,
+ BMCR_RESET);
+ dme_miibus_writereg(sc->dme_dev, DME_INT_PHY, MII_DME_DSPCR,
+ DSPCR_INIT);
+ /* Wait 100ms for it to complete. */
+ for (i = 0; i < 100; i++) {
+ int reg;
+
+ reg = dme_miibus_readreg(sc->dme_dev, DME_INT_PHY, MII_BMCR);
+ if ((reg & BMCR_RESET) == 0)
+ break;
+ DELAY(1000);
+ }
+ }
+#endif
+
+ /* Select the internal PHY and normal loopback */
+ dme_write_reg(sc, DME_NCR, NCR_LBK_NORMAL);
+ /* Clear any TX requests */
+ dme_write_reg(sc, DME_TCR, 0);
+ /* Setup backpressure thresholds to 4k and 600us */
+ dme_write_reg(sc, DME_BPTR, BPTR_BPHW(3) | BPTR_JPT(0x0f));
+ /* Setup flow control */
+ dme_write_reg(sc, DME_FCTR, FCTR_HWOT(0x3) | FCTR_LWOT(0x08));
+ /* Enable flow control */
+ dme_write_reg(sc, DME_FCR, 0xff);
+ /* Clear special modes */
+ dme_write_reg(sc, DME_SMCR, 0);
+ /* Clear TX status */
+ dme_write_reg(sc, DME_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
+ /* Clear interrrupts */
+ dme_write_reg(sc, DME_ISR, 0xff);
+ /* Set multicast address filter */
+ for (i = 0; i < 8; i++)
+ dme_write_reg(sc, DME_MAR(i), 0xff);
+ /* Set the MAC address */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ dme_write_reg(sc, DME_PAR(i), sc->dme_macaddr[i]);
+ /* Enable the RX buffer */
+ dme_write_reg(sc, DME_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
+
+ /* Enable interrupts we care about */
+ dme_write_reg(sc, DME_IMR, IMR_PAR | IMR_PRI | IMR_PTI);
+}
+
+void
+dme_prepare(struct dme_softc *sc)
+{
+ struct ifnet *ifp;
+ struct mbuf *m, *mp;
+ uint16_t total_len, len;
+
+ DME_ASSERT_LOCKED(sc);
+
+ KASSERT(sc->dme_txready == 0,
+ ("dme_prepare: called with txready set\n"));
+
+ ifp = sc->dme_ifp;
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL) {
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ DTR3("dme_prepare none, flags %#x busy %d ready %d",
+ sc->dme_ifp->if_drv_flags, sc->dme_txbusy, sc->dme_txready);
+ return; /* Nothing to transmit */
+ }
+
+ /* Element has now been removed from the queue, so we better send it */
+ BPF_MTAP(ifp, m);
+
+ /* Setup the controller to accept the writes */
+ bus_space_write_1(sc->dme_tag, sc->dme_handle, CMD_ADDR, DME_MWCMD);
+
+ /*
+ * TODO: Fix the case where an mbuf is
+ * not a multiple of the write size.
+ */
+ total_len = 0;
+ for (mp = m; mp != NULL; mp = mp->m_next) {
+ len = mp->m_len;
+
+ /* Ignore empty parts */
+ if (len == 0)
+ continue;
+
+ total_len += len;
+
+#if 0
+ bus_space_write_multi_2(sc->dme_tag, sc->dme_handle,
+ DATA_ADDR, mtod(mp, uint16_t *), (len + 1) / 2);
+#else
+ bus_space_write_multi_1(sc->dme_tag, sc->dme_handle,
+ DATA_ADDR, mtod(mp, uint8_t *), len);
+#endif
+ }
+
+ if (total_len % (sc->dme_bits >> 3) != 0)
+ panic("dme_prepare: length is not compatible with IO_MODE");
+
+ sc->dme_txlen = total_len;
+ sc->dme_txready = 1;
+ DTR3("dme_prepare done, flags %#x busy %d ready %d",
+ sc->dme_ifp->if_drv_flags, sc->dme_txbusy, sc->dme_txready);
+
+ m_freem(m);
+}
+
+void
+dme_transmit(struct dme_softc *sc)
+{
+
+ DME_ASSERT_LOCKED(sc);
+ KASSERT(sc->dme_txready, ("transmit without txready"));
+
+ dme_write_reg(sc, DME_TXPLL, sc->dme_txlen & 0xff);
+ dme_write_reg(sc, DME_TXPLH, (sc->dme_txlen >> 8) & 0xff );
+
+ /* Request to send the packet */
+ dme_read_reg(sc, DME_ISR);
+
+ dme_write_reg(sc, DME_TCR, TCR_TXREQ);
+
+ sc->dme_txready = 0;
+ sc->dme_txbusy = 1;
+ DTR3("dme_transmit done, flags %#x busy %d ready %d",
+ sc->dme_ifp->if_drv_flags, sc->dme_txbusy, sc->dme_txready);
+}
+
+
+static void
+dme_start_locked(struct ifnet *ifp)
+{
+ struct dme_softc *sc;
+
+ sc = ifp->if_softc;
+ DME_ASSERT_LOCKED(sc);
+
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING)
+ return;
+
+ DTR3("dme_start, flags %#x busy %d ready %d",
+ sc->dme_ifp->if_drv_flags, sc->dme_txbusy, sc->dme_txready);
+ KASSERT(sc->dme_txbusy == 0 || sc->dme_txready == 0,
+ ("dme: send without empty queue\n"));
+
+ dme_prepare(sc);
+
+ if (sc->dme_txbusy == 0) {
+ /* We are ready to transmit right away */
+ dme_transmit(sc);
+ dme_prepare(sc); /* Prepare next one */
+ }
+ /*
+ * We need to wait until the current packet has
+ * been transmitted.
+ */
+ if (sc->dme_txready != 0)
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+}
+
+static void
+dme_start(struct ifnet *ifp)
+{
+ struct dme_softc *sc;
+
+ sc = ifp->if_softc;
+ DME_LOCK(sc);
+ dme_start_locked(ifp);
+ DME_UNLOCK(sc);
+}
+
+static void
+dme_stop(struct dme_softc *sc)
+{
+ struct ifnet *ifp;
+
+ DME_ASSERT_LOCKED(sc);
+ /* Disable receiver */
+ dme_write_reg(sc, DME_RCR, 0x00);
+ /* Mask interrupts */
+ dme_write_reg(sc, DME_IMR, 0x00);
+ /* Stop poll */
+ callout_stop(&sc->dme_tick_ch);
+
+ ifp = sc->dme_ifp;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+
+ DTR3("dme_stop, flags %#x busy %d ready %d",
+ sc->dme_ifp->if_drv_flags, sc->dme_txbusy, sc->dme_txready);
+ sc->dme_txbusy = 0;
+ sc->dme_txready = 0;
+}
+
+static int
+dme_rxeof(struct dme_softc *sc)
+{
+ struct ifnet *ifp;
+ struct mbuf *m;
+ int len, i;
+
+ DME_ASSERT_LOCKED(sc);
+
+ ifp = sc->dme_ifp;
+
+ /* Read the first byte to check it correct */
+ (void)dme_read_reg(sc, DME_MRCMDX);
+ i = bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR);
+ switch(bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR)) {
+ case 1:
+ /* Correct value */
+ break;
+ case 0:
+ return 1;
+ default:
+ /* Error */
+ return -1;
+ }
+
+ i = dme_read_reg(sc, DME_MRRL);
+ i |= dme_read_reg(sc, DME_MRRH) << 8;
+
+ len = dme_read_reg(sc, DME_ROCR);
+
+ bus_space_write_1(sc->dme_tag, sc->dme_handle, CMD_ADDR, DME_MRCMD);
+ len = 0;
+ switch(sc->dme_bits) {
+ case 8:
+ i = bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR);
+ i <<= 8;
+ i |= bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR);
+
+ len = bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR);
+ len |= bus_space_read_1(sc->dme_tag, sc->dme_handle,
+ DATA_ADDR) << 8;
+ break;
+ case 16:
+ bus_space_read_2(sc->dme_tag, sc->dme_handle, DATA_ADDR);
+ len = bus_space_read_2(sc->dme_tag, sc->dme_handle, DATA_ADDR);
+ break;
+ case 32:
+ {
+ uint32_t reg;
+
+ reg = bus_space_read_4(sc->dme_tag, sc->dme_handle, DATA_ADDR);
+ len = reg & 0xFFFF;
+ break;
+ }
+ }
+
+ MGETHDR(m, M_NOWAIT, MT_DATA);
+ if (m == NULL)
+ return -1;
+
+ if (len > MHLEN - ETHER_ALIGN) {
+ MCLGET(m, M_NOWAIT);
+ if (!(m->m_flags & M_EXT)) {
+ m_freem(m);
+ return -1;
+ }
+ }
+
+ m->m_pkthdr.rcvif = ifp;
+ m->m_len = m->m_pkthdr.len = len;
+ m_adj(m, ETHER_ALIGN);
+
+ /* Read the data */
+#if 0
+ bus_space_read_multi_2(sc->dme_tag, sc->dme_handle, DATA_ADDR,
+ mtod(m, uint16_t *), (len + 1) / 2);
+#else
+ bus_space_read_multi_1(sc->dme_tag, sc->dme_handle, DATA_ADDR,
+ mtod(m, uint8_t *), len);
+#endif
+ if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
+ DME_UNLOCK(sc);
+ (*ifp->if_input)(ifp, m);
+ DME_LOCK(sc);
+
+ return 0;
+}
+
+static void
+dme_tick(void *arg)
+{
+ struct dme_softc *sc;
+ struct mii_data *mii;
+
+ sc = (struct dme_softc *)arg;
+
+ /* Probably too frequent? */
+ mii = device_get_softc(sc->dme_miibus);
+ mii_tick(mii);
+
+ callout_reset(&sc->dme_tick_ch, hz, dme_tick, sc);
+}
+
+static void
+dme_intr(void *arg)
+{
+ struct dme_softc *sc;
+ uint32_t intr_status;
+
+ sc = (struct dme_softc *)arg;
+
+ DME_LOCK(sc);
+
+ intr_status = dme_read_reg(sc, DME_ISR);
+ dme_write_reg(sc, DME_ISR, intr_status);
+
+ DTR4("dme_intr flags %#x busy %d ready %d intr %#x",
+ sc->dme_ifp->if_drv_flags, sc->dme_txbusy,
+ sc->dme_txready, intr_status);
+
+ if (intr_status & ISR_PT) {
+ uint8_t nsr, tx_status;
+
+ sc->dme_txbusy = 0;
+
+ nsr = dme_read_reg(sc, DME_NSR);
+
+ if (nsr & NSR_TX1END)
+ tx_status = dme_read_reg(sc, DME_TSR1);
+ else if (nsr & NSR_TX2END)
+ tx_status = dme_read_reg(sc, DME_TSR2);
+ else
+ tx_status = 1;
+
+ DTR4("dme_intr flags %#x busy %d ready %d nsr %#x",
+ sc->dme_ifp->if_drv_flags, sc->dme_txbusy,
+ sc->dme_txready, nsr);
+
+ /* Prepare packet to send if none is currently pending */
+ if (sc->dme_txready == 0)
+ dme_prepare(sc);
+ /* Send the packet out of one is waiting for transmit */
+ if (sc->dme_txready != 0) {
+ /* Initiate transmission of the prepared packet */
+ dme_transmit(sc);
+ /* Prepare next packet to send */
+ dme_prepare(sc);
+ /*
+ * We need to wait until the current packet has
+ * been transmitted.
+ */
+ if (sc->dme_txready != 0)
+ sc->dme_ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ }
+ }
+
+ if (intr_status & ISR_PR) {
+ /* Read the packets off the device */
+ while (dme_rxeof(sc) == 0)
+ continue;
+ }
+ DME_UNLOCK(sc);
+}
+
+static void
+dme_setmode(struct dme_softc *sc)
+{
+}
+
+static int
+dme_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ struct dme_softc *sc;
+ struct mii_data *mii;
+ struct ifreq *ifr;
+ int error = 0;
+
+ sc = ifp->if_softc;
+ ifr = (struct ifreq *)data;
+
+ switch (command) {
+ case SIOCSIFFLAGS:
+ /*
+ * Switch interface state between "running" and
+ * "stopped", reflecting the UP flag.
+ */
+ DME_LOCK(sc);
+ if (ifp->if_flags & IFF_UP) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ dme_init_locked(sc);
+ }
+ } else {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ dme_stop(sc);
+ }
+ }
+ dme_setmode(sc);
+ DME_UNLOCK(sc);
+ break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ mii = device_get_softc(sc->dme_miibus);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+ break;
+ default:
+ error = ether_ioctl(ifp, command, data);
+ break;
+ }
+ return (error);
+}
+
+static void dme_init_locked(struct dme_softc *sc)
+{
+ struct ifnet *ifp = sc->dme_ifp;
+
+ DME_ASSERT_LOCKED(sc);
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+
+ dme_reset(sc);
+ dme_config(sc);
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ callout_reset(&sc->dme_tick_ch, hz, dme_tick, sc);
+}
+
+static void
+dme_init(void *xcs)
+{
+ struct dme_softc *sc = xcs;
+
+ DME_LOCK(sc);
+ dme_init_locked(sc);
+ DME_UNLOCK(sc);
+}
+
+static int
+dme_ifmedia_upd(struct ifnet *ifp)
+{
+ struct dme_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = device_get_softc(sc->dme_miibus);
+
+ DME_LOCK(sc);
+ mii_mediachg(mii);
+ DME_UNLOCK(sc);
+
+ return (0);
+}
+
+static void
+dme_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct dme_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = device_get_softc(sc->dme_miibus);
+
+ DME_LOCK(sc);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+ DME_UNLOCK(sc);
+}
+
+static struct ofw_compat_data compat_data[] = {
+ { "davicom,dm9000", true },
+ { NULL, false }
+};
+
+static int
+dme_probe(device_t dev)
+{
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+ device_set_desc(dev, "Davicom DM9000");
+ return (0);
+}
+
+static int
+dme_attach(device_t dev)
+{
+ struct dme_softc *sc;
+ struct ifnet *ifp;
+ int error, rid;
+ uint32_t data;
+
+ sc = device_get_softc(dev);
+ sc->dme_dev = dev;
+
+ error = 0;
+
+ mtx_init(&sc->dme_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+ MTX_DEF);
+ callout_init_mtx(&sc->dme_tick_ch, &sc->dme_mtx, 0);
+
+ rid = 0;
+ sc->dme_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->dme_res == NULL) {
+ device_printf(dev, "unable to map memory\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ rid = 0;
+ sc->dme_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->dme_irq == NULL) {
+ device_printf(dev, "unable to map memory\n");
+ error = ENXIO;
+ goto fail;
+ }
+ /*
+ * Power the chip up, if necessary
+ */
+ error = regulator_get_by_ofw_property(dev, 0, "vcc-supply", &sc->dme_vcc_regulator);
+ if (error == 0) {
+ error = regulator_enable(sc->dme_vcc_regulator);
+ if (error != 0) {
+ device_printf(dev, "unable to enable power supply\n");
+ error = ENXIO;
+ goto fail;
+ }
+ }
+
+ /*
+ * Delay a little. This seems required on rev-1 boards (green.)
+ */
+ DELAY(100000);
+
+ /* Bring controller out of reset */
+ error = ofw_gpiobus_parse_gpios(dev, "reset-gpios", &sc->gpio_rset);
+ if (error > 1) {
+ device_printf(dev, "too many reset gpios\n");
+ sc->gpio_rset = NULL;
+ error = ENXIO;
+ goto fail;
+ }
+
+ if (sc->gpio_rset != NULL) {
+ error = GPIO_PIN_SET(sc->gpio_rset->dev, sc->gpio_rset->pin, 0);
+ if (error != 0) {
+ device_printf(dev, "Cannot configure GPIO pin %d on %s\n",
+ sc->gpio_rset->pin, device_get_nameunit(sc->gpio_rset->dev));
+ goto fail;
+ }
+
+ error = GPIO_PIN_SETFLAGS(sc->gpio_rset->dev, sc->gpio_rset->pin,
+ GPIO_PIN_OUTPUT);
+ if (error != 0) {
+ device_printf(dev, "Cannot configure GPIO pin %d on %s\n",
+ sc->gpio_rset->pin, device_get_nameunit(sc->gpio_rset->dev));
+ goto fail;
+ }
+
+ DELAY(2000);
+
+ error = GPIO_PIN_SET(sc->gpio_rset->dev, sc->gpio_rset->pin, 1);
+ if (error != 0) {
+ device_printf(dev, "Cannot configure GPIO pin %d on %s\n",
+ sc->gpio_rset->pin, device_get_nameunit(sc->gpio_rset->dev));
+ goto fail;
+ }
+
+ DELAY(4000);
+ } else
+ device_printf(dev, "Unable to find reset GPIO\n");
+
+ sc->dme_tag = rman_get_bustag(sc->dme_res);
+ sc->dme_handle = rman_get_bushandle(sc->dme_res);
+
+ /* Reset the chip as soon as possible */
+ dme_reset(sc);
+
+ /* Figure IO mode */
+ switch((dme_read_reg(sc, DME_ISR) >> 6) & 0x03) {
+ case 0:
+ /* 16 bit */
+ sc->dme_bits = 16;
+ break;
+ case 1:
+ /* 32 bit */
+ sc->dme_bits = 32;
+ break;
+ case 2:
+ /* 8 bit */
+ sc->dme_bits = 8;
+ break;
+ default:
+ /* reserved */
+ device_printf(dev, "Unable to determine device mode\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ DELAY(100000);
+
+ /* Read vendor and device id's */
+ data = dme_read_reg(sc, DME_VIDH) << 8;
+ data |= dme_read_reg(sc, DME_VIDL);
+ device_printf(dev, "Vendor ID: 0x%04x\n", data);
+
+ /* Read vendor and device id's */
+ data = dme_read_reg(sc, DME_PIDH) << 8;
+ data |= dme_read_reg(sc, DME_PIDL);
+ device_printf(dev, "Product ID: 0x%04x\n", data);
+
+ /* Chip revision */
+ data = dme_read_reg(sc, DME_CHIPR);
+ device_printf(dev, "Revision: 0x%04x\n", data);
+ if (data != DME_CHIP_DM9000A && data != DME_CHIP_DM9000B)
+ data = DME_CHIP_DM9000;
+ sc->dme_rev = data;
+
+ device_printf(dev, "using %d-bit IO mode\n", sc->dme_bits);
+ KASSERT(sc->dme_bits == 8, ("wrong io mode"));
+
+ /* Try to figure our mac address */
+ dme_get_macaddr(sc);
+
+ /* Configure chip after reset */
+ dme_config(sc);
+
+ ifp = sc->dme_ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ device_printf(dev, "unable to allocate ifp\n");
+ error = ENOSPC;
+ goto fail;
+ }
+ ifp->if_softc = sc;
+
+ /* Setup MII */
+ error = mii_attach(dev, &sc->dme_miibus, ifp, dme_ifmedia_upd,
+ dme_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ /* This should never happen as the DM9000 contains it's own PHY */
+ if (error != 0) {
+ device_printf(dev, "PHY probe failed\n");
+ goto fail;
+ }
+
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = dme_start;
+ ifp->if_ioctl = dme_ioctl;
+ ifp->if_init = dme_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+
+ ether_ifattach(ifp, sc->dme_macaddr);
+
+ error = bus_setup_intr(dev, sc->dme_irq, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, dme_intr, sc, &sc->dme_intrhand);
+ if (error) {
+ device_printf(dev, "couldn't set up irq\n");
+ ether_ifdetach(ifp);
+ goto fail;
+ }
+fail:
+ if (error != 0)
+ dme_detach(dev);
+ return (error);
+}
+
+static int
+dme_detach(device_t dev)
+{
+ struct dme_softc *sc;
+ struct ifnet *ifp;
+
+ sc = device_get_softc(dev);
+ KASSERT(mtx_initialized(&sc->dme_mtx), ("dme mutex not initialized"));
+
+ ifp = sc->dme_ifp;
+
+ if (device_is_attached(dev)) {
+ DME_LOCK(sc);
+ dme_stop(sc);
+ DME_UNLOCK(sc);
+ ether_ifdetach(ifp);
+ callout_drain(&sc->dme_tick_ch);
+ }
+
+ if (sc->dme_miibus)
+ device_delete_child(dev, sc->dme_miibus);
+ bus_generic_detach(dev);
+
+ if (sc->dme_vcc_regulator != 0)
+ regulator_release(sc->dme_vcc_regulator);
+ if (sc->dme_intrhand)
+ bus_teardown_intr(dev, sc->dme_irq, sc->dme_intrhand);
+ if (sc->dme_irq)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dme_irq);
+ if (sc->dme_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->dme_res);
+
+ if (ifp != NULL)
+ if_free(ifp);
+
+ mtx_destroy(&sc->dme_mtx);
+
+ return (0);
+}
+
+/*
+ * The MII bus interface
+ */
+static int
+dme_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct dme_softc *sc;
+ int i, rval;
+
+ /* We have up to 4 PHY's */
+ if (phy >= 4)
+ return (0);
+
+ sc = device_get_softc(dev);
+
+ /* Send the register to read to the phy and start the read */
+ dme_write_reg(sc, DME_EPAR, (phy << 6) | reg);
+ dme_write_reg(sc, DME_EPCR, EPCR_EPOS | EPCR_ERPRR);
+
+ /* Wait for the data to be read */
+ for (i = 0; i < DME_TIMEOUT; i++) {
+ if ((dme_read_reg(sc, DME_EPCR) & EPCR_ERRE) == 0)
+ break;
+ DELAY(1);
+ }
+
+ /* Clear the comand */
+ dme_write_reg(sc, DME_EPCR, 0);
+
+ if (i == DME_TIMEOUT)
+ return (0);
+
+ rval = (dme_read_reg(sc, DME_EPDRH) << 8) | dme_read_reg(sc, DME_EPDRL);
+ return (rval);
+}
+
+static int
+dme_miibus_writereg(device_t dev, int phy, int reg, int data)
+{
+ struct dme_softc *sc;
+ int i;
+
+ /* We have up to 4 PHY's */
+ if (phy > 3)
+ return (0);
+
+ sc = device_get_softc(dev);
+
+ /* Send the register and data to write to the phy */
+ dme_write_reg(sc, DME_EPAR, (phy << 6) | reg);
+ dme_write_reg(sc, DME_EPDRL, data & 0xFF);
+ dme_write_reg(sc, DME_EPDRH, (data >> 8) & 0xFF);
+ /* Start the write */
+ dme_write_reg(sc, DME_EPCR, EPCR_EPOS | EPCR_ERPRW);
+
+ /* Wait for the data to be written */
+ for (i = 0; i < DME_TIMEOUT; i++) {
+ if ((dme_read_reg(sc, DME_EPCR) & EPCR_ERRE) == 0)
+ break;
+ DELAY(1);
+ }
+
+ /* Clear the comand */
+ dme_write_reg(sc, DME_EPCR, 0);
+
+ return (0);
+}
+
+static device_method_t dme_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, dme_probe),
+ DEVMETHOD(device_attach, dme_attach),
+ DEVMETHOD(device_detach, dme_detach),
+
+ /* bus interface, for miibus */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, dme_miibus_readreg),
+ DEVMETHOD(miibus_writereg, dme_miibus_writereg),
+
+ { 0, 0 }
+};
+
+static driver_t dme_driver = {
+ "dme",
+ dme_methods,
+ sizeof(struct dme_softc)
+};
+
+static devclass_t dme_devclass;
+
+MODULE_DEPEND(dme, ether, 1, 1, 1);
+MODULE_DEPEND(dme, miibus, 1, 1, 1);
+DRIVER_MODULE(dme, simplebus, dme_driver, dme_devclass, 0, 0);
+DRIVER_MODULE(miibus, dme, miibus_driver, miibus_devclass, 0, 0);
+
diff --git a/sys/dev/dme/if_dmereg.h b/sys/dev/dme/if_dmereg.h
new file mode 100644
index 000000000000..9a5456f7d674
--- /dev/null
+++ b/sys/dev/dme/if_dmereg.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2010 Andrew Turner
+ * 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 __IF_DMEREG_H__
+#define __IF_DMEREG_H__
+
+/*
+ * DM9000 register definitions
+ */
+#define DME_NCR 0x00
+#define NCR_EXT_PHY (1<<7)
+#define NCR_WAKEEN (1<<6)
+#define NCR_FCOL (1<<4)
+#define NCR_FDX (1<<3)
+#define NCR_LBK_NORMAL (0<<1)
+#define NCR_LBK_MAC (1<<1)
+#define NCR_LBK_PHY (2<<1)
+#define NCR_RST (1<<0)
+#define DME_NSR 0x01
+#define NSR_SPEED (1<<7)
+#define NSR_LINKST (1<<6)
+#define NSR_WAKEST (1<<5)
+#define NSR_TX2END (1<<3)
+#define NSR_TX1END (1<<2)
+#define NSR_RXOV (1<<1)
+#define DME_TCR 0x02
+#define TCR_TJDIS (1<<6)
+#define TCR_EXCECM (1<<5)
+#define TCR_PAD_DIS2 (1<<4)
+#define TCR_PAD_CRC2 (1<<3)
+#define TCR_PAD_DIS1 (1<<2)
+#define TCR_PAD_CRC1 (1<<1)
+#define TCR_TXREQ (1<<0)
+#define DME_TSR1 0x03
+#define DME_TSR2 0x04
+#define DME_RCR 0x05
+#define RCR_WTDIS (1<<6)
+#define RCR_DIS_LONG (1<<5)
+#define RCR_DIS_CRC (1<<4)
+#define RCR_ALL (1<<3)
+#define RCR_RUNT (1<<2)
+#define RCR_PRMSC (1<<1)
+#define RCR_RXEN (1<<0)
+#define DME_RSR 0x06
+#define DME_ROCR 0x07
+#define DME_BPTR 0x08
+#define BPTR_BPHW(v) (((v) & 0x0f) << 4)
+#define BPTR_JPT(v) (((v) & 0x0f) << 0)
+#define DME_FCTR 0x09
+#define FCTR_HWOT(v) (((v) & 0x0f) << 4)
+#define FCTR_LWOT(v) (((v) & 0x0f) << 0)
+#define DME_FCR 0x0A
+#define DME_EPCR 0x0B
+#define EPCR_REEP (1<<5)
+#define EPCR_WEP (1<<4)
+#define EPCR_EPOS (1<<3)
+#define EPCR_ERPRR (1<<2)
+#define EPCR_ERPRW (1<<1)
+#define EPCR_ERRE (1<<0)
+#define DME_EPAR 0x0C
+#define DME_EPDRL 0x0D
+#define DME_EPDRH 0x0E
+#define DME_WCR 0x0F
+#define DME_PAR_BASE 0x10
+#define DME_PAR(n) (DME_PAR_BASE + n)
+#define DME_MAR_BASE 0x16
+#define DME_MAR(n) (DME_MAR_BASE + n)
+#define DME_GPCR 0x1E
+#define DME_GPR 0x1F
+#define DME_TRPAL 0x22
+#define DME_TRPAH 0x23
+#define DME_RWPAL 0x24
+#define DME_RWPAH 0x25
+#define DME_VIDL 0x28
+#define DME_VIDH 0x29
+#define DME_PIDL 0x2A
+#define DME_PIDH 0x2B
+#define DME_CHIPR 0x2C
+#define DME_SMCR 0x2F
+#define DME_MRCMDX 0xF0
+#define DME_MRCMD 0xF2
+#define DME_MRRL 0xF4
+#define DME_MRRH 0xF5
+#define DME_MWCMDX 0xF6
+#define DME_MWCMD 0xF8
+#define DME_MWRL 0xFA
+#define DME_MWRH 0xFB
+#define DME_TXPLL 0xFC
+#define DME_TXPLH 0xFD
+#define DME_ISR 0xFE
+#define ISR_LNKCHG (1<<5)
+#define ISR_UDRUN (1<<4)
+#define ISR_ROO (1<<3)
+#define ISR_ROS (1<<2)
+#define ISR_PT (1<<1)
+#define ISR_PR (1<<0)
+
+#define DME_IMR 0xFF
+#define IMR_PAR (1<<7)
+#define IMR_LNKCHGI (1<<5)
+#define IMR_UDRUNI (1<<4)
+#define IMR_ROOI (1<<3)
+#define IMR_ROI (1<<2)
+#define IMR_PTI (1<<1)
+#define IMR_PRI (1<<0)
+
+/* Extra PHY register from DM9000B */
+#define MII_DME_DSPCR 0x1B
+#define DSPCR_INIT 0xE100
+
+#endif /* __DMEREGS_H__ */
+
diff --git a/sys/dev/dme/if_dmevar.h b/sys/dev/dme/if_dmevar.h
new file mode 100644
index 000000000000..49fdcac4549b
--- /dev/null
+++ b/sys/dev/dme/if_dmevar.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 Andrew Turner
+ * 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 __IF_DMEVAR_H__
+#define __IF_DMEVAR_H__
+
+#define DME_LOCK(cs) mtx_lock(&(sc)->dme_mtx)
+#define DME_UNLOCK(cs) mtx_unlock(&(sc)->dme_mtx)
+#define DME_ASSERT_LOCKED(sc) mtx_assert(&(sc)->dme_mtx, MA_OWNED);
+
+#define DME_TIMEOUT 1000
+
+#endif /* __IF_DMEVAR_H__ */
+
diff --git a/sys/dev/dpaa/bman_fdt.c b/sys/dev/dpaa/bman_fdt.c
index c7950270e34d..454af67ae6b1 100644
--- a/sys/dev/dpaa/bman_fdt.c
+++ b/sys/dev/dpaa/bman_fdt.c
@@ -33,11 +33,10 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>
+#include <sys/smp.h>
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
-
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/ofw_subr.h>
@@ -107,7 +106,8 @@ static driver_t bm_portals_driver = {
};
static devclass_t bm_portals_devclass;
-DRIVER_MODULE(bman_portals, ofwbus, bm_portals_driver, bm_portals_devclass, 0, 0);
+EARLY_DRIVER_MODULE(bman_portals, ofwbus, bm_portals_driver,
+ bm_portals_devclass, 0, 0, BUS_PASS_BUS);
static void
get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep)
@@ -123,7 +123,7 @@ static int
bman_portals_fdt_probe(device_t dev)
{
- if (!ofw_bus_is_compatible(dev, "bman-portals"))
+ if (!ofw_bus_is_compatible(dev, "fsl,bman-portals"))
return (ENXIO);
device_set_desc(dev, BMAN_PORT_DEVSTR);
@@ -131,6 +131,25 @@ bman_portals_fdt_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
+static phandle_t
+bman_portal_find_cpu(int cpu)
+{
+ phandle_t node;
+ pcell_t reg;
+
+ node = OF_finddevice("/cpus");
+ if (node == -1)
+ return (node);
+
+ for (node = OF_child(node); node != 0; node = OF_peer(node)) {
+ if (OF_getprop(node, "reg", &reg, sizeof(reg)) <= 0)
+ continue;
+ if (reg == cpu)
+ return (node);
+ }
+ return (-1);
+}
+
static int
bman_portals_fdt_attach(device_t dev)
{
@@ -154,13 +173,17 @@ bman_portals_fdt_attach(device_t dev)
/* Find portals tied to CPUs */
for (child = OF_child(node); child != 0; child = OF_peer(child)) {
- if (!fdt_is_compatible(child, "fsl,bman-portal")) {
+ if (cpus >= mp_ncpus)
+ break;
+ if (!ofw_bus_node_is_compatible(child, "fsl,bman-portal")) {
continue;
}
/* Checkout related cpu */
if (OF_getprop(child, "cpu-handle", (void *)&cpu,
sizeof(cpu)) <= 0) {
- continue;
+ cpu = bman_portal_find_cpu(cpus);
+ if (cpu <= 0)
+ continue;
}
/* Acquire cpu number */
cpu_node = OF_instance_to_package(cpu);
@@ -171,9 +194,6 @@ bman_portals_fdt_attach(device_t dev)
cpus++;
- if (cpus > MAXCPU)
- break;
-
if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) {
device_printf(dev, "could not set up devinfo\n");
continue;
diff --git a/sys/dev/dpaa/dpaa.c b/sys/dev/dpaa/dpaa.c
deleted file mode 100644
index 95c04b4d5960..000000000000
--- a/sys/dev/dpaa/dpaa.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*-
- * Copyright (c) 2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/ktr.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-#include <sys/malloc.h>
-
-#include <dev/fdt/fdt_common.h>
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-#include <dev/ofw/openfirm.h>
-
-#include "opt_platform.h"
-
-static MALLOC_DEFINE(M_DPAA, "dpaa", "dpaa devices information");
-
-static int dpaa_probe(device_t dev);
-static int dpaa_attach(device_t dev);
-
-static const struct ofw_bus_devinfo *dpaa_get_devinfo(device_t bus,
- device_t child);
-
-struct dpaa_softc {
-
-};
-
-struct dpaa_devinfo {
- struct ofw_bus_devinfo di_ofw;
-};
-
-static device_method_t dpaa_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, dpaa_probe),
- DEVMETHOD(device_attach, dpaa_attach),
- DEVMETHOD(device_detach, bus_generic_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
-
- /* OFW bus interface */
- DEVMETHOD(ofw_bus_get_devinfo, dpaa_get_devinfo),
- DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
- DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
- DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
- DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
- DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
-
- {0, 0}
-};
-
-static driver_t dpaa_driver = {
- "dpaa",
- dpaa_methods,
- sizeof(struct dpaa_softc),
-};
-
-static devclass_t dpaa_devclass;
-DRIVER_MODULE_ORDERED(dpaa, ofwbus, dpaa_driver, dpaa_devclass, 0, 0,
- SI_ORDER_ANY);
-
-static int
-dpaa_probe(device_t dev)
-{
-
- if (!ofw_bus_is_compatible(dev, "fsl,dpaa"))
- return (ENXIO);
-
- device_set_desc(dev, "Freescale Data Path Acceleration Architecture");
-
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-dpaa_attach(device_t dev)
-{
- device_t dev_child;
- phandle_t dt_node, dt_child, enet_node;
- struct dpaa_devinfo *di;
- pcell_t cell_index;
-
- cell_index = 0;
- /*
- * Walk dpaa and add direct subordinates as our children.
- */
- dt_node = ofw_bus_get_node(dev);
- dt_child = OF_child(dt_node);
-
- for (; dt_child != 0; dt_child = OF_peer(dt_child)) {
-
- /* Check and process 'status' property. */
- if (!(fdt_is_enabled(dt_child)))
- continue;
-
- di = (struct dpaa_devinfo *)malloc(sizeof(*di), M_DPAA,
- M_WAITOK | M_ZERO);
-
- if (ofw_bus_gen_setup_devinfo(&di->di_ofw, dt_child) != 0) {
- free(di, M_DPAA);
- device_printf(dev, "could not set up devinfo\n");
- continue;
- }
-
- /*
- * dTSEC number from SoC is equal to number get from
- * dts file.
- */
- if (OF_getprop(dt_child, "fsl,fman-mac",
- (void *)&enet_node, sizeof(enet_node)) == -1) {
- device_printf(dev, "Could not get fsl,fman-mac "
- "from dts\n");
- continue;
- }
-
- if ((enet_node = OF_instance_to_package(enet_node)) == -1) {
- device_printf(dev, "Could not get enet node\n");
- continue;
- }
-
- if (OF_getprop(enet_node, "cell-index",
- (void *)&cell_index, sizeof(cell_index)) == -1) {
- device_printf(dev, "Could not get cell-index from enet "
- "node\n");
- continue;
- }
-
- /* Add newbus device for this FDT node */
- dev_child = device_add_child(dev, "dtsec", (int)cell_index);
- if (dev_child == NULL) {
- device_printf(dev, "could not add child: %s\n",
- di->di_ofw.obd_name);
- ofw_bus_gen_destroy_devinfo(&di->di_ofw);
- free(di, M_DPAA);
- continue;
- }
-
-#ifdef DEBUG
- device_printf(dev, "added child: %s\n\n", di->di_ofw.obd_name);
-#endif
-
- device_set_ivars(dev_child, di);
- }
-
- return (bus_generic_attach(dev));
-}
-
-static const struct ofw_bus_devinfo *
-dpaa_get_devinfo(device_t bus, device_t child)
-{
- struct dpaa_devinfo *di;
-
- di = device_get_ivars(child);
- return (&di->di_ofw);
-}
diff --git a/sys/dev/dpaa/fman.c b/sys/dev/dpaa/fman.c
index ee1f0cd8bf2e..4a90c10514a5 100644
--- a/sys/dev/dpaa/fman.c
+++ b/sys/dev/dpaa/fman.c
@@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <sys/malloc.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/fdt/simplebus.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -50,6 +49,8 @@ __FBSDID("$FreeBSD$");
#include "fman.h"
+static MALLOC_DEFINE(M_FMAN, "fman", "fman devices information");
+
/**
* @group FMan private defines.
* @{
@@ -259,6 +260,8 @@ fman_attach(device_t dev)
{
struct fman_softc *sc;
struct fman_config cfg;
+ pcell_t qchan_range[2];
+ phandle_t node;
sc = device_get_softc(dev);
sc->sc_base.dev = dev;
@@ -270,8 +273,14 @@ fman_attach(device_t dev)
return (ENXIO);
}
- XX_TrackInit();
-
+ node = ofw_bus_get_node(dev);
+ if (OF_getencprop(node, "fsl,qman-channel-range", qchan_range,
+ sizeof(qchan_range)) <= 0) {
+ device_printf(dev, "Missing QMan channel range property!\n");
+ return (ENXIO);
+ }
+ sc->qman_chan_base = qchan_range[0];
+ sc->qman_chan_count = qchan_range[1];
sc->mem_rid = 0;
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
RF_ACTIVE | RF_SHAREABLE);
@@ -379,4 +388,21 @@ fman_shutdown(device_t dev)
return (0);
}
+int
+fman_qman_channel_id(device_t dev, int port)
+{
+ struct fman_softc *sc;
+ int qman_port_id[] = {0x31, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
+ 0x2f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->qman_chan_count; i++) {
+ if (qman_port_id[i] == port)
+ return (sc->qman_chan_base + i);
+ }
+
+ return (0);
+}
+
/** @} */
diff --git a/sys/dev/dpaa/fman.h b/sys/dev/dpaa/fman.h
index 52bc61762c2b..96cdd86b0362 100644
--- a/sys/dev/dpaa/fman.h
+++ b/sys/dev/dpaa/fman.h
@@ -42,6 +42,8 @@ struct fman_softc {
int mem_rid;
int irq_rid;
int err_irq_rid;
+ int qman_chan_base;
+ int qman_chan_count;
t_Handle fm_handle;
t_Handle muram_handle;
@@ -59,6 +61,7 @@ int fman_resume(device_t dev);
int fman_shutdown(device_t dev);
int fman_read_ivar(device_t dev, device_t child, int index,
uintptr_t *result);
+int fman_qman_channel_id(device_t, int);
/** @} */
uint32_t fman_get_clock(struct fman_softc *sc);
diff --git a/sys/dev/dpaa/if_dtsec.c b/sys/dev/dpaa/if_dtsec.c
index d5f771251e3e..38f27fc847c3 100644
--- a/sys/dev/dpaa/if_dtsec.c
+++ b/sys/dev/dpaa/if_dtsec.c
@@ -49,8 +49,6 @@ __FBSDID("$FreeBSD$");
#include <net/if_types.h>
#include <net/if_arp.h>
-#include <dev/fdt/fdt_common.h>
-#include <dev/fdt/simplebus.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include <dev/ofw/ofw_bus.h>
@@ -584,8 +582,6 @@ dtsec_attach(device_t dev)
if (XX_MallocSmartInit() != E_OK)
return (ENXIO);
- XX_TrackInit();
-
/* Init locks */
mtx_init(&sc->sc_lock, device_get_nameunit(dev),
"DTSEC Global Lock", MTX_DEF);
diff --git a/sys/dev/dpaa/if_dtsec_fdt.c b/sys/dev/dpaa/if_dtsec_fdt.c
index 49666f155a1d..b653fbd5f0c1 100644
--- a/sys/dev/dpaa/if_dtsec_fdt.c
+++ b/sys/dev/dpaa/if_dtsec_fdt.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
-#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/openfirm.h>
@@ -88,7 +87,7 @@ static driver_t dtsec_driver = {
};
static devclass_t dtsec_devclass;
-DRIVER_MODULE(dtsec, dpaa, dtsec_driver, dtsec_devclass, 0, 0);
+DRIVER_MODULE(dtsec, fman, dtsec_driver, dtsec_devclass, 0, 0);
DRIVER_MODULE(miibus, dtsec, miibus_driver, miibus_devclass, 0, 0);
MODULE_DEPEND(dtsec, ether, 1, 1, 1);
MODULE_DEPEND(dtsec, miibus, 1, 1, 1);
@@ -97,7 +96,8 @@ static int
dtsec_fdt_probe(device_t dev)
{
- if (!ofw_bus_is_compatible(dev, "fsl,dpa-ethernet"))
+ if (!ofw_bus_is_compatible(dev, "fsl,fman-dtsec") &&
+ !ofw_bus_is_compatible(dev, "fsl,fman-xgec"))
return (ENXIO);
device_set_desc(dev, "Freescale Data Path Triple Speed Ethernet "
@@ -120,9 +120,7 @@ find_mdio(phandle_t phy_node, device_t mac, device_t *mdio_dev)
if (phy_node <= 0)
return (ENOENT);
- if (fman_get_dev(&bus) < 0)
- return (ENOENT);
-
+ bus = device_get_parent(mac);
*mdio_dev = ofw_bus_find_child_device_by_phandle(bus, phy_node);
return (0);
@@ -132,21 +130,13 @@ static int
dtsec_fdt_attach(device_t dev)
{
struct dtsec_softc *sc;
- phandle_t node, enet_node, phy_node;
+ phandle_t enet_node, phy_node;
phandle_t fman_rxtx_node[2];
char phy_type[6];
+ pcell_t fman_tx_cell;
sc = device_get_softc(dev);
- node = ofw_bus_get_node(dev);
-
- if (OF_getprop(node, "fsl,fman-mac", (void *)&enet_node,
- sizeof(enet_node)) == -1) {
- device_printf(dev, "Could not load fsl,fman-mac property "
- "from DTS\n");
- return (ENXIO);
- }
-
- enet_node = OF_instance_to_package(enet_node);
+ enet_node = ofw_bus_get_node(dev);
if (OF_getprop(enet_node, "local-mac-address",
(void *)sc->sc_mac_addr, 6) == -1) {
@@ -156,9 +146,9 @@ dtsec_fdt_attach(device_t dev)
}
/* Get link speed */
- if (fdt_is_compatible(enet_node, "fsl,fman-1g-mac") != 0)
+ if (ofw_bus_is_compatible(dev, "fsl,fman-dtsec") != 0)
sc->sc_eth_dev_type = ETH_DTSEC;
- else if (fdt_is_compatible(enet_node, "fsl,fman-10g-mac") != 0)
+ else if (ofw_bus_is_compatible(dev, "fsl,fman-xgec") != 0)
sc->sc_eth_dev_type = ETH_10GSEC;
else
return(ENXIO);
@@ -198,7 +188,7 @@ dtsec_fdt_attach(device_t dev)
return (ENXIO);
/* Get RX/TX port handles */
- if (OF_getprop(enet_node, "fsl,port-handles", (void *)fman_rxtx_node,
+ if (OF_getprop(enet_node, "fsl,fman-ports", (void *)fman_rxtx_node,
sizeof(fman_rxtx_node)) <= 0)
return (ENXIO);
@@ -211,10 +201,12 @@ dtsec_fdt_attach(device_t dev)
fman_rxtx_node[0] = OF_instance_to_package(fman_rxtx_node[0]);
fman_rxtx_node[1] = OF_instance_to_package(fman_rxtx_node[1]);
- if (fdt_is_compatible(fman_rxtx_node[0], "fsl,fman-port-1g-rx") == 0)
+ if (ofw_bus_node_is_compatible(fman_rxtx_node[0],
+ "fsl,fman-v2-port-rx") == 0)
return (ENXIO);
- if (fdt_is_compatible(fman_rxtx_node[1], "fsl,fman-port-1g-tx") == 0)
+ if (ofw_bus_node_is_compatible(fman_rxtx_node[1],
+ "fsl,fman-v2-port-tx") == 0)
return (ENXIO);
/* Get RX port HW id */
@@ -227,11 +219,12 @@ dtsec_fdt_attach(device_t dev)
sizeof(sc->sc_port_tx_hw_id)) <= 0)
return (ENXIO);
- /* Get QMan channel */
- if (OF_getprop(fman_rxtx_node[1], "fsl,qman-channel-id",
- (void *)&sc->sc_port_tx_qman_chan,
- sizeof(sc->sc_port_tx_qman_chan)) <= 0)
+ if (OF_getprop(fman_rxtx_node[1], "cell-index", &fman_tx_cell,
+ sizeof(fman_tx_cell)) <= 0)
return (ENXIO);
+ /* Get QMan channel */
+ sc->sc_port_tx_qman_chan = fman_qman_channel_id(device_get_parent(dev),
+ fman_tx_cell);
return (dtsec_attach(dev));
}
diff --git a/sys/dev/dpaa/if_dtsec_rm.c b/sys/dev/dpaa/if_dtsec_rm.c
index 06e9f0165ed2..66c20e3175ae 100644
--- a/sys/dev/dpaa/if_dtsec_rm.c
+++ b/sys/dev/dpaa/if_dtsec_rm.c
@@ -136,7 +136,6 @@ static void
dtsec_rm_fi_free(struct dtsec_softc *sc, struct dtsec_rm_frame_info *fi)
{
- XX_UntrackAddress(fi);
uma_zfree(sc->sc_fi_zone, fi);
}
/** @} */
@@ -323,6 +322,7 @@ dtsec_rm_pool_rx_init(struct dtsec_softc *sc)
DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dtsec_rm_pool_rx_depleted, sc, NULL,
NULL);
if (sc->sc_rx_pool == NULL) {
+ device_printf(sc->sc_dev, "NULL rx pool somehow\n");
dtsec_rm_pool_rx_free(sc);
return (EIO);
}
diff --git a/sys/dev/dpaa/qman_fdt.c b/sys/dev/dpaa/qman_fdt.c
index 69f128cf649f..e37196d54aac 100644
--- a/sys/dev/dpaa/qman_fdt.c
+++ b/sys/dev/dpaa/qman_fdt.c
@@ -33,11 +33,10 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>
+#include <sys/smp.h>
#include <machine/bus.h>
-#include <dev/fdt/fdt_common.h>
-
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/ofw_subr.h>
@@ -107,7 +106,8 @@ static driver_t qm_portals_driver = {
};
static devclass_t qm_portals_devclass;
-DRIVER_MODULE(qman_portals, ofwbus, qm_portals_driver, qm_portals_devclass, 0, 0);
+EARLY_DRIVER_MODULE(qman_portals, ofwbus, qm_portals_driver,
+ qm_portals_devclass, 0, 0, BUS_PASS_BUS);
static void
get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep)
@@ -123,7 +123,7 @@ static int
qman_portals_fdt_probe(device_t dev)
{
- if (!ofw_bus_is_compatible(dev, "qman-portals"))
+ if (!ofw_bus_is_compatible(dev, "fsl,qman-portals"))
return (ENXIO);
device_set_desc(dev, BMAN_PORT_DEVSTR);
@@ -131,36 +131,87 @@ qman_portals_fdt_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
+static phandle_t
+qman_portal_find_cpu(int cpu)
+{
+ phandle_t node;
+ pcell_t reg;
+
+ node = OF_finddevice("/cpus");
+ if (node == -1)
+ return (-1);
+
+ for (node = OF_child(node); node != 0; node = OF_peer(node)) {
+ if (OF_getprop(node, "reg", &reg, sizeof(reg)) <= 0)
+ continue;
+ if (reg == cpu)
+ return (node);
+ }
+ return (-1);
+}
+
static int
qman_portals_fdt_attach(device_t dev)
{
struct dpaa_portals_softc *sc;
- struct resource_list_entry *rle;
phandle_t node, child, cpu_node;
- vm_paddr_t portal_pa;
+ vm_paddr_t portal_pa, portal_par_pa;
vm_size_t portal_size;
- uint32_t addr, size;
+ uint32_t addr, paddr, size;
ihandle_t cpu;
int cpu_num, cpus, intr_rid;
struct dpaa_portals_devinfo di;
struct ofw_bus_devinfo ofw_di = {};
+ cell_t *range;
+ int nrange;
+ int i;
cpus = 0;
sc = device_get_softc(dev);
sc->sc_dev = dev;
node = ofw_bus_get_node(dev);
+
+ /* Get this node's range */
+ get_addr_props(ofw_bus_get_node(device_get_parent(dev)), &paddr, &size);
get_addr_props(node, &addr, &size);
+ nrange = OF_getencprop_alloc(node, "ranges",
+ sizeof(*range), (void **)&range);
+ if (nrange < addr + paddr + size)
+ return (ENXIO);
+ portal_pa = portal_par_pa = 0;
+ portal_size = 0;
+ for (i = 0; i < addr; i++) {
+ portal_pa <<= 32;
+ portal_pa |= range[i];
+ }
+ for (; i < paddr + addr; i++) {
+ portal_par_pa <<= 32;
+ portal_par_pa |= range[i];
+ }
+ portal_pa += portal_par_pa;
+ for (; i < size + paddr + addr; i++) {
+ portal_size = (uintmax_t)portal_size << 32;
+ portal_size |= range[i];
+ }
+ OF_prop_free(range);
+ sc->sc_dp_size = portal_size;
+ sc->sc_dp_pa = portal_pa;
+
/* Find portals tied to CPUs */
for (child = OF_child(node); child != 0; child = OF_peer(child)) {
- if (!fdt_is_compatible(child, "fsl,qman-portal")) {
+ if (cpus >= mp_ncpus)
+ break;
+ if (!ofw_bus_node_is_compatible(child, "fsl,qman-portal")) {
continue;
}
/* Checkout related cpu */
if (OF_getprop(child, "cpu-handle", (void *)&cpu,
sizeof(cpu)) <= 0) {
- continue;
+ cpu = qman_portal_find_cpu(cpus);
+ if (cpu <= 0)
+ continue;
}
/* Acquire cpu number */
cpu_node = OF_instance_to_package(cpu);
@@ -171,9 +222,6 @@ qman_portals_fdt_attach(device_t dev)
cpus++;
- if (cpus > MAXCPU)
- break;
-
if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) {
device_printf(dev, "could not set up devinfo\n");
continue;
@@ -194,17 +242,6 @@ qman_portals_fdt_attach(device_t dev)
continue;
}
di.di_intr_rid = intr_rid;
-
- ofw_reg_to_paddr(child, 0, &portal_pa, &portal_size, NULL);
- rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 0);
-
- if (sc->sc_dp_pa == 0)
- sc->sc_dp_pa = portal_pa - rle->start;
-
- portal_size = rle->end + 1;
- rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 1);
- portal_size = ulmax(rle->end + 1, portal_size);
- sc->sc_dp_size = ulmax(sc->sc_dp_size, portal_size);
if (dpaa_portal_alloc_res(dev, &di, cpu_num))
goto err;
diff --git a/sys/dev/drm2/drmP.h b/sys/dev/drm2/drmP.h
index 508fc3099179..51f407c14a94 100644
--- a/sys/dev/drm2/drmP.h
+++ b/sys/dev/drm2/drmP.h
@@ -1204,17 +1204,6 @@ int drm_mmap_single(struct cdev *kdev, vm_ooffset_t *offset,
vm_size_t size, struct vm_object **obj_res, int nprot);
d_poll_t drm_poll;
- /* Memory management support (drm_memory.h) */
-extern void drm_free_agp(DRM_AGP_MEM * handle, int pages);
-extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
-#ifdef FREEBSD_NOTYET
-extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
- struct page **pages,
- unsigned long num_pages,
- uint32_t gtt_offset,
- uint32_t type);
-#endif /* FREEBSD_NOTYET */
-extern int drm_unbind_agp(DRM_AGP_MEM * handle);
/* Misc. IOCTL support (drm_ioctl.h) */
extern int drm_irq_by_busid(struct drm_device *dev, void *data,
@@ -1363,32 +1352,6 @@ extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
- /* AGP/GART support (drm_agpsupport.h) */
-extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
-extern int drm_agp_acquire(struct drm_device *dev);
-extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int drm_agp_release(struct drm_device *dev);
-extern int drm_agp_release_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
-extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info);
-extern int drm_agp_info_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
-extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
-extern int drm_agp_free_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
-extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
-extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
/* Stub support (drm_stub.h) */
extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
@@ -1814,5 +1777,175 @@ int ttm_bo_mmap_single(struct ttm_bo_device *bdev, vm_ooffset_t *offset,
struct ttm_buffer_object;
void ttm_bo_release_mmap(struct ttm_buffer_object *bo);
+#if __OS_HAS_AGP
+ /* Memory management support (drm_memory.h) */
+extern void drm_free_agp(DRM_AGP_MEM * handle, int pages);
+extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
+#ifdef FREEBSD_NOTYET
+extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
+ struct page **pages,
+ unsigned long num_pages,
+ uint32_t gtt_offset,
+ uint32_t type);
+#endif /* FREEBSD_NOTYET */
+extern int drm_unbind_agp(DRM_AGP_MEM * handle);
+
+ /* AGP/GART support (drm_agpsupport.h) */
+extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+extern int drm_agp_acquire(struct drm_device *dev);
+extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_release(struct drm_device *dev);
+extern int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
+extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info);
+extern int drm_agp_info_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
+extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
+extern int drm_agp_free_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
+extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
+extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+#else
+
+static inline void drm_free_agp(DRM_AGP_MEM * handle, int pages)
+{
+}
+
+static inline int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
+{
+ return -ENODEV;
+}
+
+static inline int drm_unbind_agp(DRM_AGP_MEM * handle)
+{
+ return -ENODEV;
+}
+#ifdef FREEBSD_NOTYET
+static inline struct agp_memory *drm_agp_bind_pages(struct drm_device *dev,
+ struct page **pages,
+ unsigned long num_pages,
+ uint32_t gtt_offset,
+ uint32_t type)
+{
+ return NULL;
+}
+#endif
+static inline struct drm_agp_head *drm_agp_init(struct drm_device *dev)
+{
+ return NULL;
+}
+
+static inline void drm_agp_clear(struct drm_device *dev)
+{
+}
+
+static inline int drm_agp_acquire(struct drm_device *dev)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_release(struct drm_device *dev)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_enable(struct drm_device *dev,
+ struct drm_agp_mode mode)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_info(struct drm_device *dev,
+ struct drm_agp_info *info)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_info_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_alloc(struct drm_device *dev,
+ struct drm_agp_buffer *request)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_free(struct drm_device *dev,
+ struct drm_agp_buffer *request)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_free_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_unbind(struct drm_device *dev,
+ struct drm_agp_binding *request)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_bind(struct drm_device *dev,
+ struct drm_agp_binding *request)
+{
+ return -ENODEV;
+}
+
+static inline int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return -ENODEV;
+}
+
+#endif /* __OS_HAS_AGP */
+
#endif /* __KERNEL__ */
#endif
diff --git a/sys/dev/drm2/drm_memory.c b/sys/dev/drm2/drm_memory.c
index a25e5a288ee1..226c2c15734b 100644
--- a/sys/dev/drm2/drm_memory.c
+++ b/sys/dev/drm2/drm_memory.c
@@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drmP.h>
+#define vunmap(handle)
+
#if __OS_HAS_AGP
static void *agp_remap(unsigned long offset, unsigned long size,
struct drm_device * dev)
@@ -50,8 +52,6 @@ static void *agp_remap(unsigned long offset, unsigned long size,
return NULL;
}
-#define vunmap(handle)
-
/** Wrapper around agp_free_memory() */
void drm_free_agp(DRM_AGP_MEM * handle, int pages)
{
diff --git a/sys/dev/drm2/drm_os_freebsd.c b/sys/dev/drm2/drm_os_freebsd.c
index d8b45e8fb580..4ce8081887ba 100644
--- a/sys/dev/drm2/drm_os_freebsd.c
+++ b/sys/dev/drm2/drm_os_freebsd.c
@@ -347,6 +347,7 @@ dmi_check_system(const struct dmi_system_id *sysid)
return (res);
}
+#if __OS_HAS_MTRR
int
drm_mtrr_add(unsigned long offset, unsigned long size, unsigned int flags)
{
@@ -375,6 +376,7 @@ drm_mtrr_del(int handle __unused, unsigned long offset, unsigned long size,
strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
return (-mem_range_attr_set(&mrdesc, &act));
}
+#endif
void
drm_clflush_pages(vm_page_t *pages, unsigned long num_pages)
diff --git a/sys/dev/drm2/drm_os_freebsd.h b/sys/dev/drm2/drm_os_freebsd.h
index 3c9983838e1d..dc01c6a64595 100644
--- a/sys/dev/drm2/drm_os_freebsd.h
+++ b/sys/dev/drm2/drm_os_freebsd.h
@@ -592,8 +592,10 @@ typedef struct drm_pci_id_list
#define CONFIG_COMPAT
#endif
+#ifndef __arm__
#define CONFIG_AGP 1
#define CONFIG_MTRR 1
+#endif
#define CONFIG_FB 1
extern const char *fb_mode_option;
diff --git a/sys/dev/drm2/ttm/ttm_bo_util.c b/sys/dev/drm2/ttm/ttm_bo_util.c
index fbbaaf2029fa..c53bb21450d8 100644
--- a/sys/dev/drm2/ttm/ttm_bo_util.c
+++ b/sys/dev/drm2/ttm/ttm_bo_util.c
@@ -439,7 +439,8 @@ ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
vm_memattr_t
ttm_io_prot(uint32_t caching_flags)
{
-#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
+#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) || \
+ defined(__arm__)
if (caching_flags & TTM_PL_FLAG_WC)
return (VM_MEMATTR_WRITE_COMBINING);
else
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index fd602bf482f2..b1bf35b5e464 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -5274,6 +5274,8 @@ em_get_wakeup(device_t dev)
case e1000_ich10lan:
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
+ case e1000_pch_spt:
apme_mask = E1000_WUC_APME;
adapter->has_amt = TRUE;
eeprom_data = E1000_READ_REG(&adapter->hw, E1000_WUC);
@@ -5322,7 +5324,7 @@ em_enable_wakeup(device_t dev)
{
struct adapter *adapter = device_get_softc(dev);
if_t ifp = adapter->ifp;
- u32 pmc, ctrl, ctrl_ext, rctl;
+ u32 pmc, ctrl, ctrl_ext, rctl, wuc;
u16 status;
if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0))
@@ -5332,7 +5334,9 @@ em_enable_wakeup(device_t dev)
ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3);
E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
- E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
+ wuc = E1000_READ_REG(&adapter->hw, E1000_WUC);
+ wuc |= E1000_WUC_PME_EN;
+ E1000_WRITE_REG(&adapter->hw, E1000_WUC, wuc);
if ((adapter->hw.mac.type == e1000_ich8lan) ||
(adapter->hw.mac.type == e1000_pchlan) ||
@@ -5363,8 +5367,10 @@ em_enable_wakeup(device_t dev)
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl);
}
- if ((adapter->hw.mac.type == e1000_pchlan) ||
- (adapter->hw.mac.type == e1000_pch2lan)) {
+ if ((adapter->hw.mac.type == e1000_pchlan) ||
+ (adapter->hw.mac.type == e1000_pch2lan) ||
+ (adapter->hw.mac.type == e1000_pch_lpt) ||
+ (adapter->hw.mac.type == e1000_pch_spt)) {
if (em_enable_phy_wakeup(adapter))
return;
} else {
diff --git a/sys/dev/etherswitch/e6000sw/e6060sw.c b/sys/dev/etherswitch/e6000sw/e6060sw.c
new file mode 100644
index 000000000000..9e3d93b66d27
--- /dev/null
+++ b/sys/dev/etherswitch/e6000sw/e6060sw.c
@@ -0,0 +1,703 @@
+/*-
+ * Copyright (c) 2016 Hiroki Mori
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * 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$
+ */
+
+/*
+ * This code is Marvell 88E6060 ethernet switch support code on etherswitch
+ * framework.
+ * Current code is only support port base vlan. Not support ingress/egress
+ * trailer. This switch chip can't work vlan(4) support.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/ethernet.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <machine/bus.h>
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/mdio/mdio.h>
+
+#include <dev/etherswitch/etherswitch.h>
+
+#include "mdio_if.h"
+#include "miibus_if.h"
+#include "etherswitch_if.h"
+
+#define SMI_OFFSET 0x10
+#define CORE_REGISTER (SMI_OFFSET + 8)
+
+#define SWITCH_ID 3
+#define PORT_VLAN_MAP 6
+
+MALLOC_DECLARE(M_E6060SW);
+MALLOC_DEFINE(M_E6060SW, "e6060sw", "e6060sw data structures");
+
+struct e6060sw_softc {
+ struct mtx sc_mtx; /* serialize access to softc */
+ device_t sc_dev;
+ int vlan_mode;
+ int media; /* cpu port media */
+ int cpuport; /* which PHY is connected to the CPU */
+ int phymask; /* PHYs we manage */
+ int numports; /* number of ports */
+ int ifpport[MII_NPHY];
+ int *portphy;
+ char **ifname;
+ device_t **miibus;
+ struct ifnet **ifp;
+ struct callout callout_tick;
+ etherswitch_info_t info;
+};
+
+#define E6060SW_LOCK(_sc) \
+ mtx_lock(&(_sc)->sc_mtx)
+#define E6060SW_UNLOCK(_sc) \
+ mtx_unlock(&(_sc)->sc_mtx)
+#define E6060SW_LOCK_ASSERT(_sc, _what) \
+ mtx_assert(&(_sc)->sc_mtx, (_what))
+#define E6060SW_TRYLOCK(_sc) \
+ mtx_trylock(&(_sc)->sc_mtx)
+
+#if defined(DEBUG)
+#define DPRINTF(dev, args...) device_printf(dev, args)
+#else
+#define DPRINTF(dev, args...)
+#endif
+
+static inline int e6060sw_portforphy(struct e6060sw_softc *, int);
+static void e6060sw_tick(void *);
+static int e6060sw_ifmedia_upd(struct ifnet *);
+static void e6060sw_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+
+static int
+e6060sw_probe(device_t dev)
+{
+ int data;
+ struct e6060sw_softc *sc;
+
+ sc = device_get_softc(dev);
+ bzero(sc, sizeof(*sc));
+
+ data = MDIO_READREG(device_get_parent(dev), CORE_REGISTER, SWITCH_ID);
+ if (bootverbose)
+ device_printf(dev,"Switch Identifier Register %x\n", data);
+
+ if ((data >> 4) != 0x060) {
+ return (ENXIO);
+ }
+
+ device_set_desc_copy(dev, "Marvell 88E6060 MDIO switch driver");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+e6060sw_attach_phys(struct e6060sw_softc *sc)
+{
+ int phy, port, err;
+ char name[IFNAMSIZ];
+
+ port = 0;
+ err = 0;
+ /* PHYs need an interface, so we generate a dummy one */
+ snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev));
+ for (phy = 0; phy < sc->numports; phy++) {
+ if (((1 << phy) & sc->phymask) == 0)
+ continue;
+ sc->ifpport[phy] = port;
+ sc->portphy[port] = phy;
+ sc->ifp[port] = if_alloc(IFT_ETHER);
+ sc->ifp[port]->if_softc = sc;
+ sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST |
+ IFF_DRV_RUNNING | IFF_SIMPLEX;
+ if_initname(sc->ifp[port], name, port);
+ sc->miibus[port] = malloc(sizeof(device_t), M_E6060SW,
+ M_WAITOK | M_ZERO);
+ err = mii_attach(sc->sc_dev, sc->miibus[port], sc->ifp[port],
+ e6060sw_ifmedia_upd, e6060sw_ifmedia_sts, \
+ BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
+ DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n",
+ device_get_nameunit(*sc->miibus[port]),
+ sc->ifp[port]->if_xname);
+ if (err != 0) {
+ device_printf(sc->sc_dev,
+ "attaching PHY %d failed\n",
+ phy);
+ break;
+ }
+ ++port;
+ }
+ sc->info.es_nports = port;
+ if (sc->cpuport != -1) {
+ /* assume cpuport is last one */
+ sc->ifpport[sc->cpuport] = port;
+ sc->portphy[port] = sc->cpuport;
+ ++sc->info.es_nports;
+ }
+ return (err);
+}
+
+static int
+e6060sw_attach(device_t dev)
+{
+ struct e6060sw_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+ err = 0;
+
+ sc->sc_dev = dev;
+ mtx_init(&sc->sc_mtx, "e6060sw", NULL, MTX_DEF);
+ strlcpy(sc->info.es_name, device_get_desc(dev),
+ sizeof(sc->info.es_name));
+
+ /* XXX Defaults */
+ sc->numports = 6;
+ sc->phymask = 0x1f;
+ sc->cpuport = 5;
+ sc->media = 100;
+
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "numports", &sc->numports);
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "phymask", &sc->phymask);
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "cpuport", &sc->cpuport);
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "media", &sc->media);
+
+ sc->info.es_nvlangroups = sc->numports;
+ sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT;
+
+ sc->ifp = malloc(sizeof(struct ifnet *) * sc->numports, M_E6060SW,
+ M_WAITOK | M_ZERO);
+ sc->ifname = malloc(sizeof(char *) * sc->numports, M_E6060SW,
+ M_WAITOK | M_ZERO);
+ sc->miibus = malloc(sizeof(device_t *) * sc->numports, M_E6060SW,
+ M_WAITOK | M_ZERO);
+ sc->portphy = malloc(sizeof(int) * sc->numports, M_E6060SW,
+ M_WAITOK | M_ZERO);
+
+ /*
+ * Attach the PHYs and complete the bus enumeration.
+ */
+ err = e6060sw_attach_phys(sc);
+ if (err != 0)
+ return (err);
+
+ bus_generic_probe(dev);
+ bus_enumerate_hinted_children(dev);
+ err = bus_generic_attach(dev);
+ if (err != 0)
+ return (err);
+
+ callout_init(&sc->callout_tick, 0);
+
+ e6060sw_tick(sc);
+
+ return (err);
+}
+
+static int
+e6060sw_detach(device_t dev)
+{
+ struct e6060sw_softc *sc;
+ int i, port;
+
+ sc = device_get_softc(dev);
+
+ callout_drain(&sc->callout_tick);
+
+ for (i = 0; i < MII_NPHY; i++) {
+ if (((1 << i) & sc->phymask) == 0)
+ continue;
+ port = e6060sw_portforphy(sc, i);
+ if (sc->miibus[port] != NULL)
+ device_delete_child(dev, (*sc->miibus[port]));
+ if (sc->ifp[port] != NULL)
+ if_free(sc->ifp[port]);
+ free(sc->ifname[port], M_E6060SW);
+ free(sc->miibus[port], M_E6060SW);
+ }
+
+ free(sc->portphy, M_E6060SW);
+ free(sc->miibus, M_E6060SW);
+ free(sc->ifname, M_E6060SW);
+ free(sc->ifp, M_E6060SW);
+
+ bus_generic_detach(dev);
+ mtx_destroy(&sc->sc_mtx);
+
+ return (0);
+}
+
+/*
+ * Convert PHY number to port number.
+ */
+static inline int
+e6060sw_portforphy(struct e6060sw_softc *sc, int phy)
+{
+
+ return (sc->ifpport[phy]);
+}
+
+static inline struct mii_data *
+e6060sw_miiforport(struct e6060sw_softc *sc, int port)
+{
+
+ if (port < 0 || port > sc->numports)
+ return (NULL);
+ if (port == sc->cpuport)
+ return (NULL);
+ return (device_get_softc(*sc->miibus[port]));
+}
+
+static inline struct ifnet *
+e6060sw_ifpforport(struct e6060sw_softc *sc, int port)
+{
+
+ if (port < 0 || port > sc->numports)
+ return (NULL);
+ return (sc->ifp[port]);
+}
+
+/*
+ * Poll the status for all PHYs.
+ */
+static void
+e6060sw_miipollstat(struct e6060sw_softc *sc)
+{
+ int i, port;
+ struct mii_data *mii;
+ struct mii_softc *miisc;
+
+ E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED);
+
+ for (i = 0; i < MII_NPHY; i++) {
+ if (((1 << i) & sc->phymask) == 0)
+ continue;
+ port = e6060sw_portforphy(sc, i);
+ if ((*sc->miibus[port]) == NULL)
+ continue;
+ mii = device_get_softc(*sc->miibus[port]);
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
+ if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
+ miisc->mii_inst)
+ continue;
+ ukphy_status(miisc);
+ mii_phy_update(miisc, MII_POLLSTAT);
+ }
+ }
+}
+
+static void
+e6060sw_tick(void *arg)
+{
+ struct e6060sw_softc *sc;
+
+ sc = arg;
+
+ e6060sw_miipollstat(sc);
+ callout_reset(&sc->callout_tick, hz, e6060sw_tick, sc);
+}
+
+static void
+e6060sw_lock(device_t dev)
+{
+ struct e6060sw_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED);
+ E6060SW_LOCK(sc);
+}
+
+static void
+e6060sw_unlock(device_t dev)
+{
+ struct e6060sw_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ E6060SW_LOCK_ASSERT(sc, MA_OWNED);
+ E6060SW_UNLOCK(sc);
+}
+
+static etherswitch_info_t *
+e6060sw_getinfo(device_t dev)
+{
+ struct e6060sw_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return (&sc->info);
+}
+
+static int
+e6060sw_getport(device_t dev, etherswitch_port_t *p)
+{
+ struct e6060sw_softc *sc;
+ struct mii_data *mii;
+ struct ifmediareq *ifmr;
+ int err, phy;
+
+ sc = device_get_softc(dev);
+ ifmr = &p->es_ifmr;
+
+ if (p->es_port < 0 || p->es_port >= sc->numports)
+ return (ENXIO);
+ p->es_pvid = 0;
+
+ phy = sc->portphy[p->es_port];
+ mii = e6060sw_miiforport(sc, p->es_port);
+ if (sc->cpuport != -1 && phy == sc->cpuport) {
+ /* fill in fixed values for CPU port */
+ p->es_flags |= ETHERSWITCH_PORT_CPU;
+ ifmr->ifm_count = 0;
+ if (sc->media == 100)
+ ifmr->ifm_current = ifmr->ifm_active =
+ IFM_ETHER | IFM_100_TX | IFM_FDX;
+ else
+ ifmr->ifm_current = ifmr->ifm_active =
+ IFM_ETHER | IFM_1000_T | IFM_FDX;
+ ifmr->ifm_mask = 0;
+ ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
+ } else if (mii != NULL) {
+ err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
+ &mii->mii_media, SIOCGIFMEDIA);
+ if (err)
+ return (err);
+ } else {
+ return (ENXIO);
+ }
+ return (0);
+}
+
+static int
+e6060sw_setport(device_t dev, etherswitch_port_t *p)
+{
+ struct e6060sw_softc *sc;
+ struct ifmedia *ifm;
+ struct mii_data *mii;
+ struct ifnet *ifp;
+ int err;
+
+ sc = device_get_softc(dev);
+
+ if (p->es_port < 0 || p->es_port >= sc->numports)
+ return (ENXIO);
+
+ if (sc->portphy[p->es_port] == sc->cpuport)
+ return (ENXIO);
+
+ mii = e6060sw_miiforport(sc, p->es_port);
+ if (mii == NULL)
+ return (ENXIO);
+
+ ifp = e6060sw_ifpforport(sc, p->es_port);
+
+ ifm = &mii->mii_media;
+ err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA);
+ return (err);
+}
+
+static int
+e6060sw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
+{
+ struct e6060sw_softc *sc;
+ int data;
+
+ sc = device_get_softc(dev);
+
+ if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) {
+ vg->es_vid = ETHERSWITCH_VID_VALID;
+ vg->es_vid |= vg->es_vlangroup;
+ data = MDIO_READREG(device_get_parent(dev), CORE_REGISTER + vg->es_vlangroup, PORT_VLAN_MAP);
+ vg->es_member_ports = data & 0x3f;
+ vg->es_untagged_ports = vg->es_member_ports;
+ vg->es_fid = 0;
+ } else {
+ vg->es_vid = 0;
+ }
+ return (0);
+}
+
+static int
+e6060sw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
+{
+ struct e6060sw_softc *sc;
+ int data;
+
+ sc = device_get_softc(dev);
+
+ if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) {
+ data = MDIO_READREG(device_get_parent(dev), CORE_REGISTER + vg->es_vlangroup, PORT_VLAN_MAP);
+ data &= ~0x3f;
+ data |= vg->es_member_ports;
+ MDIO_WRITEREG(device_get_parent(dev), CORE_REGISTER + vg->es_vlangroup, PORT_VLAN_MAP, data);
+ }
+
+ return (0);
+}
+
+static void
+e6060sw_reset_vlans(device_t dev)
+{
+ struct e6060sw_softc *sc;
+ uint32_t ports;
+ int i;
+ int data;
+
+ sc = device_get_softc(dev);
+
+ for (i = 0; i <= sc->numports; i++) {
+ ports = (1 << (sc->numports + 1)) - 1;
+ ports &= ~(1 << i);
+ if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) {
+ data = i << 12;
+ } else {
+ data = 0;
+ }
+ data |= ports;
+ MDIO_WRITEREG(device_get_parent(dev), CORE_REGISTER + i, PORT_VLAN_MAP, data);
+ }
+}
+
+static int
+e6060sw_getconf(device_t dev, etherswitch_conf_t *conf)
+{
+ struct e6060sw_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /* Return the VLAN mode. */
+ conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
+ conf->vlan_mode = sc->vlan_mode;
+
+ return (0);
+}
+
+static int
+e6060sw_setconf(device_t dev, etherswitch_conf_t *conf)
+{
+ struct e6060sw_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /* Set the VLAN mode. */
+ if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) {
+ if (conf->vlan_mode == ETHERSWITCH_VLAN_PORT) {
+ sc->vlan_mode = ETHERSWITCH_VLAN_PORT;
+ } else {
+ sc->vlan_mode = 0;
+ }
+
+ /* Reset VLANs. */
+ e6060sw_reset_vlans(dev);
+ }
+
+ return (0);
+}
+
+static void
+e6060sw_statchg(device_t dev)
+{
+
+ DPRINTF(dev, "%s\n", __func__);
+}
+
+static int
+e6060sw_ifmedia_upd(struct ifnet *ifp)
+{
+ struct e6060sw_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = e6060sw_miiforport(sc, ifp->if_dunit);
+
+ DPRINTF(sc->sc_dev, "%s\n", __func__);
+ if (mii == NULL)
+ return (ENXIO);
+ mii_mediachg(mii);
+ return (0);
+}
+
+static void
+e6060sw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct e6060sw_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = e6060sw_miiforport(sc, ifp->if_dunit);
+
+ DPRINTF(sc->sc_dev, "%s\n", __func__);
+
+ if (mii == NULL)
+ return;
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+}
+
+static int
+e6060sw_readphy(device_t dev, int phy, int reg)
+{
+ struct e6060sw_softc *sc;
+ int data;
+
+ phy += SMI_OFFSET;
+
+ sc = device_get_softc(dev);
+ E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED);
+
+ if (phy < 0 || phy >= 32)
+ return (ENXIO);
+ if (reg < 0 || reg >= 32)
+ return (ENXIO);
+
+ E6060SW_LOCK(sc);
+ data = MDIO_READREG(device_get_parent(dev), phy, reg);
+ E6060SW_UNLOCK(sc);
+
+ return (data);
+}
+
+static int
+e6060sw_writephy(device_t dev, int phy, int reg, int data)
+{
+ struct e6060sw_softc *sc;
+ int err;
+
+ phy += SMI_OFFSET;
+
+ sc = device_get_softc(dev);
+ E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED);
+
+ if (phy < 0 || phy >= 32)
+ return (ENXIO);
+ if (reg < 0 || reg >= 32)
+ return (ENXIO);
+
+ E6060SW_LOCK(sc);
+ err = MDIO_WRITEREG(device_get_parent(dev), phy, reg, data);
+ E6060SW_UNLOCK(sc);
+
+ return (err);
+}
+
+/* addr is 5-8 bit is SMI Device Addres, 0-4 bit is SMI Register Address */
+
+static int
+e6060sw_readreg(device_t dev, int addr)
+{
+ int devaddr, regaddr;
+
+ devaddr = (addr >> 5) & 0xf;
+ regaddr = addr & 0x1f;
+
+ return MDIO_READREG(device_get_parent(dev), devaddr+SMI_OFFSET, regaddr);
+}
+
+/* addr is 5-8 bit is SMI Device Addres, 0-4 bit is SMI Register Address */
+
+static int
+e6060sw_writereg(device_t dev, int addr, int value)
+{
+ int devaddr, regaddr;
+
+ devaddr = (addr >> 5) & 0xf;
+ regaddr = addr & 0x1f;
+
+ return (MDIO_WRITEREG(device_get_parent(dev), devaddr+SMI_OFFSET, regaddr, value));
+}
+
+static device_method_t e6060sw_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, e6060sw_probe),
+ DEVMETHOD(device_attach, e6060sw_attach),
+ DEVMETHOD(device_detach, e6060sw_detach),
+
+ /* bus interface */
+ DEVMETHOD(bus_add_child, device_add_child_ordered),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, e6060sw_readphy),
+ DEVMETHOD(miibus_writereg, e6060sw_writephy),
+ DEVMETHOD(miibus_statchg, e6060sw_statchg),
+
+ /* MDIO interface */
+ DEVMETHOD(mdio_readreg, e6060sw_readphy),
+ DEVMETHOD(mdio_writereg, e6060sw_writephy),
+
+ /* etherswitch interface */
+ DEVMETHOD(etherswitch_lock, e6060sw_lock),
+ DEVMETHOD(etherswitch_unlock, e6060sw_unlock),
+ DEVMETHOD(etherswitch_getinfo, e6060sw_getinfo),
+ DEVMETHOD(etherswitch_readreg, e6060sw_readreg),
+ DEVMETHOD(etherswitch_writereg, e6060sw_writereg),
+ DEVMETHOD(etherswitch_readphyreg, e6060sw_readphy),
+ DEVMETHOD(etherswitch_writephyreg, e6060sw_writephy),
+ DEVMETHOD(etherswitch_getport, e6060sw_getport),
+ DEVMETHOD(etherswitch_setport, e6060sw_setport),
+ DEVMETHOD(etherswitch_getvgroup, e6060sw_getvgroup),
+ DEVMETHOD(etherswitch_setvgroup, e6060sw_setvgroup),
+ DEVMETHOD(etherswitch_setconf, e6060sw_setconf),
+ DEVMETHOD(etherswitch_getconf, e6060sw_getconf),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(e6060sw, e6060sw_driver, e6060sw_methods,
+ sizeof(struct e6060sw_softc));
+static devclass_t e6060sw_devclass;
+
+DRIVER_MODULE(e6060sw, mdio, e6060sw_driver, e6060sw_devclass, 0, 0);
+DRIVER_MODULE(miibus, e6060sw, miibus_driver, miibus_devclass, 0, 0);
+DRIVER_MODULE(mdio, e6060sw, mdio_driver, mdio_devclass, 0, 0);
+DRIVER_MODULE(etherswitch, e6060sw, etherswitch_driver, etherswitch_devclass, 0, 0);
+MODULE_VERSION(e6060sw, 1);
+MODULE_DEPEND(e6060sw, miibus, 1, 1, 1); /* XXX which versions? */
+MODULE_DEPEND(e6060sw, etherswitch, 1, 1, 1); /* XXX which versions? */
diff --git a/sys/dev/etherswitch/infineon/adm6996fc.c b/sys/dev/etherswitch/infineon/adm6996fc.c
new file mode 100644
index 000000000000..da31b7a964de
--- /dev/null
+++ b/sys/dev/etherswitch/infineon/adm6996fc.c
@@ -0,0 +1,858 @@
+/*-
+ * Copyright (c) 2016 Hiroki Mori
+ * Copyright (c) 2013 Luiz Otavio O Souza.
+ * Copyright (c) 2011-2012 Stefan Bethke.
+ * Copyright (c) 2012 Adrian Chadd.
+ * 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$
+ */
+
+/*
+ * This is Infineon ADM6996FC/M/MX driver code on etherswitch framework.
+ * Support PORT and DOT1Q VLAN.
+ * This code suppose ADM6996FC SDC/SDIO connect to SOC network interface
+ * MDC/MDIO.
+ * This code development on Netgear WGR614Cv7.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/ethernet.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <machine/bus.h>
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/mdio/mdio.h>
+
+#include <dev/etherswitch/etherswitch.h>
+
+#include "mdio_if.h"
+#include "miibus_if.h"
+#include "etherswitch_if.h"
+
+#define ADM6996FC_PRODUCT_CODE 0x7102
+
+#define ADM6996FC_SC3 0x11
+#define ADM6996FC_VF0L 0x40
+#define ADM6996FC_VF0H 0x41
+#define ADM6996FC_CI0 0xa0
+#define ADM6996FC_CI1 0xa1
+#define ADM6996FC_PHY_C0 0x200
+
+#define ADM6996FC_PC_SHIFT 4
+#define ADM6996FC_TBV_SHIFT 5
+#define ADM6996FC_PVID_SHIFT 10
+#define ADM6996FC_OPTE_SHIFT 4
+#define ADM6996FC_VV_SHIFT 15
+
+#define ADM6996FC_PHY_SIZE 0x20
+
+MALLOC_DECLARE(M_ADM6996FC);
+MALLOC_DEFINE(M_ADM6996FC, "adm6996fc", "adm6996fc data structures");
+
+struct adm6996fc_softc {
+ struct mtx sc_mtx; /* serialize access to softc */
+ device_t sc_dev;
+ int vlan_mode;
+ int media; /* cpu port media */
+ int cpuport; /* which PHY is connected to the CPU */
+ int phymask; /* PHYs we manage */
+ int numports; /* number of ports */
+ int ifpport[MII_NPHY];
+ int *portphy;
+ char **ifname;
+ device_t **miibus;
+ struct ifnet **ifp;
+ struct callout callout_tick;
+ etherswitch_info_t info;
+};
+
+#define ADM6996FC_LOCK(_sc) \
+ mtx_lock(&(_sc)->sc_mtx)
+#define ADM6996FC_UNLOCK(_sc) \
+ mtx_unlock(&(_sc)->sc_mtx)
+#define ADM6996FC_LOCK_ASSERT(_sc, _what) \
+ mtx_assert(&(_sc)->sc_mtx, (_what))
+#define ADM6996FC_TRYLOCK(_sc) \
+ mtx_trylock(&(_sc)->sc_mtx)
+
+#if defined(DEBUG)
+#define DPRINTF(dev, args...) device_printf(dev, args)
+#else
+#define DPRINTF(dev, args...)
+#endif
+
+static inline int adm6996fc_portforphy(struct adm6996fc_softc *, int);
+static void adm6996fc_tick(void *);
+static int adm6996fc_ifmedia_upd(struct ifnet *);
+static void adm6996fc_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+
+#define ADM6996FC_READREG(dev, x) \
+ MDIO_READREG(dev, ((x) >> 5), ((x) & 0x1f));
+#define ADM6996FC_WRITEREG(dev, x, v) \
+ MDIO_WRITEREG(dev, ((x) >> 5), ((x) & 0x1f), v);
+
+#define ADM6996FC_PVIDBYDATA(data1, data2) \
+ ((((data1) >> ADM6996FC_PVID_SHIFT) & 0x0f) | ((data2) << 4))
+
+static int
+adm6996fc_probe(device_t dev)
+{
+ int data1, data2;
+ int pc;
+ struct adm6996fc_softc *sc;
+
+ sc = device_get_softc(dev);
+ bzero(sc, sizeof(*sc));
+
+ data1 = ADM6996FC_READREG(device_get_parent(dev), ADM6996FC_CI0);
+ data2 = ADM6996FC_READREG(device_get_parent(dev), ADM6996FC_CI1);
+ pc = ((data2 << 16) | data1) >> ADM6996FC_PC_SHIFT;
+ if (bootverbose)
+ device_printf(dev,"Chip Identifier Register %x %x\n", data1,
+ data2);
+
+ /* check Product Code */
+ if (pc != ADM6996FC_PRODUCT_CODE) {
+ return (ENXIO);
+ }
+
+ device_set_desc_copy(dev, "Infineon ADM6996FC/M/MX MDIO switch driver");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+adm6996fc_attach_phys(struct adm6996fc_softc *sc)
+{
+ int phy, port, err;
+ char name[IFNAMSIZ];
+
+ port = 0;
+ err = 0;
+ /* PHYs need an interface, so we generate a dummy one */
+ snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev));
+ for (phy = 0; phy < sc->numports; phy++) {
+ if (((1 << phy) & sc->phymask) == 0)
+ continue;
+ sc->ifpport[phy] = port;
+ sc->portphy[port] = phy;
+ sc->ifp[port] = if_alloc(IFT_ETHER);
+ sc->ifp[port]->if_softc = sc;
+ sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST |
+ IFF_DRV_RUNNING | IFF_SIMPLEX;
+ if_initname(sc->ifp[port], name, port);
+ sc->miibus[port] = malloc(sizeof(device_t), M_ADM6996FC,
+ M_WAITOK | M_ZERO);
+ if (sc->miibus[port] == NULL) {
+ err = ENOMEM;
+ goto failed;
+ }
+ err = mii_attach(sc->sc_dev, sc->miibus[port], sc->ifp[port],
+ adm6996fc_ifmedia_upd, adm6996fc_ifmedia_sts, \
+ BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
+ DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n",
+ device_get_nameunit(*sc->miibus[port]),
+ sc->ifp[port]->if_xname);
+ if (err != 0) {
+ device_printf(sc->sc_dev,
+ "attaching PHY %d failed\n",
+ phy);
+ goto failed;
+ }
+ ++port;
+ }
+ sc->info.es_nports = port;
+ if (sc->cpuport != -1) {
+ /* assume cpuport is last one */
+ sc->ifpport[sc->cpuport] = port;
+ sc->portphy[port] = sc->cpuport;
+ ++sc->info.es_nports;
+ }
+ return (0);
+
+failed:
+ for (phy = 0; phy < sc->numports; phy++) {
+ if (((1 << phy) & sc->phymask) == 0)
+ continue;
+ port = adm6996fc_portforphy(sc, phy);
+ if (sc->miibus[port] != NULL)
+ device_delete_child(sc->sc_dev, (*sc->miibus[port]));
+ if (sc->ifp[port] != NULL)
+ if_free(sc->ifp[port]);
+ if (sc->ifname[port] != NULL)
+ free(sc->ifname[port], M_ADM6996FC);
+ if (sc->miibus[port] != NULL)
+ free(sc->miibus[port], M_ADM6996FC);
+ }
+ return (err);
+}
+
+static int
+adm6996fc_attach(device_t dev)
+{
+ struct adm6996fc_softc *sc;
+ int err;
+
+ err = 0;
+ sc = device_get_softc(dev);
+
+ sc->sc_dev = dev;
+ mtx_init(&sc->sc_mtx, "adm6996fc", NULL, MTX_DEF);
+ strlcpy(sc->info.es_name, device_get_desc(dev),
+ sizeof(sc->info.es_name));
+
+ /* ADM6996FC Defaults */
+ sc->numports = 6;
+ sc->phymask = 0x1f;
+ sc->cpuport = 5;
+ sc->media = 100;
+
+ sc->info.es_nvlangroups = 16;
+ sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOT1Q;
+
+ sc->ifp = malloc(sizeof(struct ifnet *) * sc->numports, M_ADM6996FC,
+ M_WAITOK | M_ZERO);
+ sc->ifname = malloc(sizeof(char *) * sc->numports, M_ADM6996FC,
+ M_WAITOK | M_ZERO);
+ sc->miibus = malloc(sizeof(device_t *) * sc->numports, M_ADM6996FC,
+ M_WAITOK | M_ZERO);
+ sc->portphy = malloc(sizeof(int) * sc->numports, M_ADM6996FC,
+ M_WAITOK | M_ZERO);
+
+ if (sc->ifp == NULL || sc->ifname == NULL || sc->miibus == NULL ||
+ sc->portphy == NULL) {
+ err = ENOMEM;
+ goto failed;
+ }
+
+ /*
+ * Attach the PHYs and complete the bus enumeration.
+ */
+ err = adm6996fc_attach_phys(sc);
+ if (err != 0)
+ goto failed;
+
+ bus_generic_probe(dev);
+ bus_enumerate_hinted_children(dev);
+ err = bus_generic_attach(dev);
+ if (err != 0)
+ goto failed;
+
+ callout_init(&sc->callout_tick, 0);
+
+ adm6996fc_tick(sc);
+
+ return (0);
+
+failed:
+ if (sc->portphy != NULL)
+ free(sc->portphy, M_ADM6996FC);
+ if (sc->miibus != NULL)
+ free(sc->miibus, M_ADM6996FC);
+ if (sc->ifname != NULL)
+ free(sc->ifname, M_ADM6996FC);
+ if (sc->ifp != NULL)
+ free(sc->ifp, M_ADM6996FC);
+
+ return (err);
+}
+
+static int
+adm6996fc_detach(device_t dev)
+{
+ struct adm6996fc_softc *sc;
+ int i, port;
+
+ sc = device_get_softc(dev);
+
+ callout_drain(&sc->callout_tick);
+
+ for (i = 0; i < MII_NPHY; i++) {
+ if (((1 << i) & sc->phymask) == 0)
+ continue;
+ port = adm6996fc_portforphy(sc, i);
+ if (sc->miibus[port] != NULL)
+ device_delete_child(dev, (*sc->miibus[port]));
+ if (sc->ifp[port] != NULL)
+ if_free(sc->ifp[port]);
+ free(sc->ifname[port], M_ADM6996FC);
+ free(sc->miibus[port], M_ADM6996FC);
+ }
+
+ free(sc->portphy, M_ADM6996FC);
+ free(sc->miibus, M_ADM6996FC);
+ free(sc->ifname, M_ADM6996FC);
+ free(sc->ifp, M_ADM6996FC);
+
+ bus_generic_detach(dev);
+ mtx_destroy(&sc->sc_mtx);
+
+ return (0);
+}
+
+/*
+ * Convert PHY number to port number.
+ */
+static inline int
+adm6996fc_portforphy(struct adm6996fc_softc *sc, int phy)
+{
+
+ return (sc->ifpport[phy]);
+}
+
+static inline struct mii_data *
+adm6996fc_miiforport(struct adm6996fc_softc *sc, int port)
+{
+
+ if (port < 0 || port > sc->numports)
+ return (NULL);
+ if (port == sc->cpuport)
+ return (NULL);
+ return (device_get_softc(*sc->miibus[port]));
+}
+
+static inline struct ifnet *
+adm6996fc_ifpforport(struct adm6996fc_softc *sc, int port)
+{
+
+ if (port < 0 || port > sc->numports)
+ return (NULL);
+ return (sc->ifp[port]);
+}
+
+/*
+ * Poll the status for all PHYs.
+ */
+static void
+adm6996fc_miipollstat(struct adm6996fc_softc *sc)
+{
+ int i, port;
+ struct mii_data *mii;
+ struct mii_softc *miisc;
+
+ ADM6996FC_LOCK_ASSERT(sc, MA_NOTOWNED);
+
+ for (i = 0; i < MII_NPHY; i++) {
+ if (((1 << i) & sc->phymask) == 0)
+ continue;
+ port = adm6996fc_portforphy(sc, i);
+ if ((*sc->miibus[port]) == NULL)
+ continue;
+ mii = device_get_softc(*sc->miibus[port]);
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
+ if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
+ miisc->mii_inst)
+ continue;
+ ukphy_status(miisc);
+ mii_phy_update(miisc, MII_POLLSTAT);
+ }
+ }
+}
+
+static void
+adm6996fc_tick(void *arg)
+{
+ struct adm6996fc_softc *sc;
+
+ sc = arg;
+
+ adm6996fc_miipollstat(sc);
+ callout_reset(&sc->callout_tick, hz, adm6996fc_tick, sc);
+}
+
+static void
+adm6996fc_lock(device_t dev)
+{
+ struct adm6996fc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ ADM6996FC_LOCK_ASSERT(sc, MA_NOTOWNED);
+ ADM6996FC_LOCK(sc);
+}
+
+static void
+adm6996fc_unlock(device_t dev)
+{
+ struct adm6996fc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ ADM6996FC_LOCK_ASSERT(sc, MA_OWNED);
+ ADM6996FC_UNLOCK(sc);
+}
+
+static etherswitch_info_t *
+adm6996fc_getinfo(device_t dev)
+{
+ struct adm6996fc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return (&sc->info);
+}
+
+static int
+adm6996fc_getport(device_t dev, etherswitch_port_t *p)
+{
+ struct adm6996fc_softc *sc;
+ struct mii_data *mii;
+ struct ifmediareq *ifmr;
+ device_t parent;
+ int err, phy;
+ int data1, data2;
+
+ int bcaddr[6] = {0x01, 0x03, 0x05, 0x07, 0x08, 0x09};
+ int vidaddr[6] = {0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c};
+
+ sc = device_get_softc(dev);
+ ifmr = &p->es_ifmr;
+
+ if (p->es_port < 0 || p->es_port >= sc->numports)
+ return (ENXIO);
+
+ parent = device_get_parent(dev);
+
+ if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
+ data1 = ADM6996FC_READREG(parent, bcaddr[p->es_port]);
+ data2 = ADM6996FC_READREG(parent, vidaddr[p->es_port]);
+ /* only port 4 is hi bit */
+ if (p->es_port == 4)
+ data2 = (data2 >> 8) & 0xff;
+ else
+ data2 = data2 & 0xff;
+
+ p->es_pvid = ADM6996FC_PVIDBYDATA(data1, data2);
+ if (((data1 >> ADM6996FC_OPTE_SHIFT) & 0x01) == 1)
+ p->es_flags |= ETHERSWITCH_PORT_ADDTAG;
+ else
+ p->es_flags |= ETHERSWITCH_PORT_STRIPTAG;
+ } else {
+ p->es_pvid = 0;
+ }
+
+ phy = sc->portphy[p->es_port];
+ mii = adm6996fc_miiforport(sc, p->es_port);
+ if (sc->cpuport != -1 && phy == sc->cpuport) {
+ /* fill in fixed values for CPU port */
+ p->es_flags |= ETHERSWITCH_PORT_CPU;
+ ifmr->ifm_count = 0;
+ if (sc->media == 100)
+ ifmr->ifm_current = ifmr->ifm_active =
+ IFM_ETHER | IFM_100_TX | IFM_FDX;
+ else
+ ifmr->ifm_current = ifmr->ifm_active =
+ IFM_ETHER | IFM_1000_T | IFM_FDX;
+ ifmr->ifm_mask = 0;
+ ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
+ } else if (mii != NULL) {
+ err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
+ &mii->mii_media, SIOCGIFMEDIA);
+ if (err)
+ return (err);
+ } else {
+ return (ENXIO);
+ }
+ return (0);
+}
+
+static int
+adm6996fc_setport(device_t dev, etherswitch_port_t *p)
+{
+ struct adm6996fc_softc *sc;
+ struct ifmedia *ifm;
+ struct mii_data *mii;
+ struct ifnet *ifp;
+ device_t parent;
+ int err;
+ int data;
+
+ int bcaddr[6] = {0x01, 0x03, 0x05, 0x07, 0x08, 0x09};
+ int vidaddr[6] = {0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c};
+
+ sc = device_get_softc(dev);
+ parent = device_get_parent(dev);
+
+ if (p->es_port < 0 || p->es_port >= sc->numports)
+ return (ENXIO);
+
+ if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
+ data = ADM6996FC_READREG(parent, bcaddr[p->es_port]);
+ data &= ~(0xf << 10);
+ data |= (p->es_pvid & 0xf) << ADM6996FC_PVID_SHIFT;
+ ADM6996FC_WRITEREG(parent, bcaddr[p->es_port], data);
+ data = ADM6996FC_READREG(parent, vidaddr[p->es_port]);
+ /* only port 4 is hi bit */
+ if (p->es_port == 4) {
+ data &= ~(0xff << 8);
+ data = data | (((p->es_pvid >> 4) & 0xff) << 8);
+ } else {
+ data &= ~0xff;
+ data = data | ((p->es_pvid >> 4) & 0xff);
+ }
+ ADM6996FC_WRITEREG(parent, vidaddr[p->es_port], data);
+ err = 0;
+ } else {
+ if (sc->portphy[p->es_port] == sc->cpuport)
+ return (ENXIO);
+ }
+
+ if (sc->portphy[p->es_port] != sc->cpuport) {
+ mii = adm6996fc_miiforport(sc, p->es_port);
+ if (mii == NULL)
+ return (ENXIO);
+
+ ifp = adm6996fc_ifpforport(sc, p->es_port);
+
+ ifm = &mii->mii_media;
+ err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA);
+ }
+ return (err);
+}
+
+static int
+adm6996fc_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
+{
+ struct adm6996fc_softc *sc;
+ device_t parent;
+ int datahi, datalo;
+
+ sc = device_get_softc(dev);
+ parent = device_get_parent(dev);
+
+ if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) {
+ if (vg->es_vlangroup <= 5) {
+ vg->es_vid = ETHERSWITCH_VID_VALID;
+ vg->es_vid |= vg->es_vlangroup;
+ datalo = ADM6996FC_READREG(parent,
+ ADM6996FC_VF0L + 2 * vg->es_vlangroup);
+ datahi = ADM6996FC_READREG(parent,
+ ADM6996FC_VF0H + 2 * vg->es_vlangroup);
+
+ vg->es_member_ports = datalo & 0x3f;
+ vg->es_untagged_ports = vg->es_member_ports;
+ vg->es_fid = 0;
+ } else {
+ vg->es_vid = 0;
+ }
+ } else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
+ datalo = ADM6996FC_READREG(parent,
+ ADM6996FC_VF0L + 2 * vg->es_vlangroup);
+ datahi = ADM6996FC_READREG(parent,
+ ADM6996FC_VF0H + 2 * vg->es_vlangroup);
+
+ if (datahi & (1 << ADM6996FC_VV_SHIFT)) {
+ vg->es_vid = ETHERSWITCH_VID_VALID;
+ vg->es_vid |= datahi & 0xfff;
+ vg->es_member_ports = datalo & 0x3f;
+ vg->es_untagged_ports = (~datalo >> 6) & 0x3f;
+ vg->es_fid = 0;
+ } else {
+ vg->es_fid = 0;
+ }
+ } else {
+ vg->es_fid = 0;
+ }
+
+ return (0);
+}
+
+static int
+adm6996fc_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
+{
+ struct adm6996fc_softc *sc;
+ device_t parent;
+
+ sc = device_get_softc(dev);
+ parent = device_get_parent(dev);
+
+ if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) {
+ ADM6996FC_WRITEREG(parent, ADM6996FC_VF0L + 2 * vg->es_vlangroup,
+ vg->es_member_ports);
+ } else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
+ ADM6996FC_WRITEREG(parent, ADM6996FC_VF0L + 2 * vg->es_vlangroup,
+ vg->es_member_ports | ((~vg->es_untagged_ports & 0x3f)<< 6));
+ ADM6996FC_WRITEREG(parent, ADM6996FC_VF0H + 2 * vg->es_vlangroup,
+ (1 << ADM6996FC_VV_SHIFT) | vg->es_vid);
+ }
+
+ return (0);
+}
+
+static int
+adm6996fc_getconf(device_t dev, etherswitch_conf_t *conf)
+{
+ struct adm6996fc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /* Return the VLAN mode. */
+ conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
+ conf->vlan_mode = sc->vlan_mode;
+
+ return (0);
+}
+
+static int
+adm6996fc_setconf(device_t dev, etherswitch_conf_t *conf)
+{
+ struct adm6996fc_softc *sc;
+ device_t parent;
+ int i;
+ int data;
+ int bcaddr[6] = {0x01, 0x03, 0x05, 0x07, 0x08, 0x09};
+
+ sc = device_get_softc(dev);
+ parent = device_get_parent(dev);
+
+ if ((conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) == 0)
+ return (0);
+
+ if (conf->vlan_mode == ETHERSWITCH_VLAN_PORT) {
+ sc->vlan_mode = ETHERSWITCH_VLAN_PORT;
+ data = ADM6996FC_READREG(parent, ADM6996FC_SC3);
+ data &= ~(1 << ADM6996FC_TBV_SHIFT);
+ ADM6996FC_WRITEREG(parent, ADM6996FC_SC3, data);
+ for (i = 0;i <= 5; ++i) {
+ data = ADM6996FC_READREG(parent, bcaddr[i]);
+ data &= ~(0xf << 10);
+ data |= (i << 10);
+ ADM6996FC_WRITEREG(parent, bcaddr[i], data);
+ ADM6996FC_WRITEREG(parent, ADM6996FC_VF0L + 2 * i,
+ 0x003f);
+ ADM6996FC_WRITEREG(parent, ADM6996FC_VF0H + 2 * i,
+ (1 << ADM6996FC_VV_SHIFT) | 1);
+ }
+ } else if (conf->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
+ sc->vlan_mode = ETHERSWITCH_VLAN_DOT1Q;
+ data = ADM6996FC_READREG(parent, ADM6996FC_SC3);
+ data |= (1 << ADM6996FC_TBV_SHIFT);
+ ADM6996FC_WRITEREG(parent, ADM6996FC_SC3, data);
+ for (i = 0;i <= 5; ++i) {
+ data = ADM6996FC_READREG(parent, bcaddr[i]);
+ /* Private VID set 1 */
+ data &= ~(0xf << 10);
+ data |= (1 << 10);
+ /* Output Packet Tagging Enable */
+ if (i == 5)
+ data |= (1 << 4);
+ ADM6996FC_WRITEREG(parent, bcaddr[i], data);
+ }
+ for (i = 2;i <= 15; ++i) {
+ ADM6996FC_WRITEREG(parent, ADM6996FC_VF0H + 2 * i,
+ 0x0000);
+ }
+ } else {
+ /*
+ ADM6996FC have no VLAN off. Then set Port base and
+ add all port to member. Use VLAN Filter 1 is reset
+ default.
+ */
+ sc->vlan_mode = 0;
+ data = ADM6996FC_READREG(parent, ADM6996FC_SC3);
+ data &= ~(1 << ADM6996FC_TBV_SHIFT);
+ ADM6996FC_WRITEREG(parent, ADM6996FC_SC3, data);
+ for (i = 0;i <= 5; ++i) {
+ data = ADM6996FC_READREG(parent, bcaddr[i]);
+ data &= ~(0xf << 10);
+ data |= (1 << 10);
+ if (i == 5)
+ data &= ~(1 << 4);
+ ADM6996FC_WRITEREG(parent, bcaddr[i], data);
+ }
+ /* default setting */
+ ADM6996FC_WRITEREG(parent, ADM6996FC_VF0L + 2, 0x003f);
+ ADM6996FC_WRITEREG(parent, ADM6996FC_VF0H + 2,
+ (1 << ADM6996FC_VV_SHIFT) | 1);
+ }
+
+
+ return (0);
+}
+
+static void
+adm6996fc_statchg(device_t dev)
+{
+
+ DPRINTF(dev, "%s\n", __func__);
+}
+
+static int
+adm6996fc_ifmedia_upd(struct ifnet *ifp)
+{
+ struct adm6996fc_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = adm6996fc_miiforport(sc, ifp->if_dunit);
+
+ DPRINTF(sc->sc_dev, "%s\n", __func__);
+ if (mii == NULL)
+ return (ENXIO);
+ mii_mediachg(mii);
+ return (0);
+}
+
+static void
+adm6996fc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct adm6996fc_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = adm6996fc_miiforport(sc, ifp->if_dunit);
+
+ DPRINTF(sc->sc_dev, "%s\n", __func__);
+
+ if (mii == NULL)
+ return;
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+}
+
+static int
+adm6996fc_readphy(device_t dev, int phy, int reg)
+{
+ struct adm6996fc_softc *sc;
+ int data;
+
+ sc = device_get_softc(dev);
+ ADM6996FC_LOCK_ASSERT(sc, MA_NOTOWNED);
+
+ if (phy < 0 || phy >= 32)
+ return (ENXIO);
+ if (reg < 0 || reg >= 32)
+ return (ENXIO);
+
+ ADM6996FC_LOCK(sc);
+ data = ADM6996FC_READREG(device_get_parent(dev),
+ (ADM6996FC_PHY_C0 + ADM6996FC_PHY_SIZE * phy) + reg);
+ ADM6996FC_UNLOCK(sc);
+
+ return (data);
+}
+
+static int
+adm6996fc_writephy(device_t dev, int phy, int reg, int data)
+{
+ struct adm6996fc_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+ ADM6996FC_LOCK_ASSERT(sc, MA_NOTOWNED);
+
+ if (phy < 0 || phy >= 32)
+ return (ENXIO);
+ if (reg < 0 || reg >= 32)
+ return (ENXIO);
+
+ ADM6996FC_LOCK(sc);
+ err = ADM6996FC_WRITEREG(device_get_parent(dev),
+ (ADM6996FC_PHY_C0 + ADM6996FC_PHY_SIZE * phy) + reg, data);
+ ADM6996FC_UNLOCK(sc);
+
+ return (err);
+}
+
+static int
+adm6996fc_readreg(device_t dev, int addr)
+{
+
+ return ADM6996FC_READREG(device_get_parent(dev), addr);
+}
+
+static int
+adm6996fc_writereg(device_t dev, int addr, int value)
+{
+ int err;
+
+ err = ADM6996FC_WRITEREG(device_get_parent(dev), addr, value);
+ return (err);
+}
+
+static device_method_t adm6996fc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, adm6996fc_probe),
+ DEVMETHOD(device_attach, adm6996fc_attach),
+ DEVMETHOD(device_detach, adm6996fc_detach),
+
+ /* bus interface */
+ DEVMETHOD(bus_add_child, device_add_child_ordered),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, adm6996fc_readphy),
+ DEVMETHOD(miibus_writereg, adm6996fc_writephy),
+ DEVMETHOD(miibus_statchg, adm6996fc_statchg),
+
+ /* MDIO interface */
+ DEVMETHOD(mdio_readreg, adm6996fc_readphy),
+ DEVMETHOD(mdio_writereg, adm6996fc_writephy),
+
+ /* etherswitch interface */
+ DEVMETHOD(etherswitch_lock, adm6996fc_lock),
+ DEVMETHOD(etherswitch_unlock, adm6996fc_unlock),
+ DEVMETHOD(etherswitch_getinfo, adm6996fc_getinfo),
+ DEVMETHOD(etherswitch_readreg, adm6996fc_readreg),
+ DEVMETHOD(etherswitch_writereg, adm6996fc_writereg),
+ DEVMETHOD(etherswitch_readphyreg, adm6996fc_readphy),
+ DEVMETHOD(etherswitch_writephyreg, adm6996fc_writephy),
+ DEVMETHOD(etherswitch_getport, adm6996fc_getport),
+ DEVMETHOD(etherswitch_setport, adm6996fc_setport),
+ DEVMETHOD(etherswitch_getvgroup, adm6996fc_getvgroup),
+ DEVMETHOD(etherswitch_setvgroup, adm6996fc_setvgroup),
+ DEVMETHOD(etherswitch_setconf, adm6996fc_setconf),
+ DEVMETHOD(etherswitch_getconf, adm6996fc_getconf),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(adm6996fc, adm6996fc_driver, adm6996fc_methods,
+ sizeof(struct adm6996fc_softc));
+static devclass_t adm6996fc_devclass;
+
+DRIVER_MODULE(adm6996fc, mdio, adm6996fc_driver, adm6996fc_devclass, 0, 0);
+DRIVER_MODULE(miibus, adm6996fc, miibus_driver, miibus_devclass, 0, 0);
+DRIVER_MODULE(mdio, adm6996fc, mdio_driver, mdio_devclass, 0, 0);
+DRIVER_MODULE(etherswitch, adm6996fc, etherswitch_driver, etherswitch_devclass,
+ 0, 0);
+MODULE_VERSION(adm6996fc, 1);
+MODULE_DEPEND(adm6996fc, miibus, 1, 1, 1); /* XXX which versions? */
+MODULE_DEPEND(adm6996fc, etherswitch, 1, 1, 1); /* XXX which versions? */
diff --git a/sys/dev/etherswitch/ip17x/ip175c.c b/sys/dev/etherswitch/ip17x/ip175c.c
index 30614a424170..c87543bc5b15 100644
--- a/sys/dev/etherswitch/ip17x/ip175c.c
+++ b/sys/dev/etherswitch/ip17x/ip175c.c
@@ -234,6 +234,13 @@ ip175c_get_vlan_mode(struct ip17x_softc *sc)
void
ip175c_attach(struct ip17x_softc *sc)
{
+ uint32_t data;
+
+ data = ip17x_readphy(sc->sc_dev, IP175C_MII_PHY, IP175C_MII_CTL_REG);
+ device_printf(sc->sc_dev, "MII: %x\n", data);
+ /* check mii1 interface if disabled then phy4 and mac4 hold on switch */
+ if((data & (1 << IP175C_MII_MII1_RMII_EN)) == 0)
+ sc->phymask |= 0x10;
sc->hal.ip17x_reset = ip175c_reset;
sc->hal.ip17x_hw_setup = ip175c_hw_setup;
diff --git a/sys/dev/etherswitch/ip17x/ip175c.h b/sys/dev/etherswitch/ip17x/ip175c.h
index 8abb4b696196..2b9e05665d28 100644
--- a/sys/dev/etherswitch/ip17x/ip175c.h
+++ b/sys/dev/etherswitch/ip17x/ip175c.h
@@ -35,6 +35,9 @@
#define IP175C_MODE_REG 31
#define IP175C_RESET_PHY 30
#define IP175C_RESET_REG 0
+#define IP175C_MII_PHY 31
+#define IP175C_MII_CTL_REG 5
+#define IP175C_MII_MII1_RMII_EN 8
#define IP175C_LAST_VLAN 15
diff --git a/sys/dev/etherswitch/rtl8366/rtl8366rb.c b/sys/dev/etherswitch/rtl8366/rtl8366rb.c
index d14f4660130e..6e990d979969 100644
--- a/sys/dev/etherswitch/rtl8366/rtl8366rb.c
+++ b/sys/dev/etherswitch/rtl8366/rtl8366rb.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2015-2016 Hiroki Mori.
* Copyright (c) 2011-2012 Stefan Bethke.
* All rights reserved.
*
@@ -26,6 +27,8 @@
* $FreeBSD$
*/
+#include "opt_etherswitch.h"
+
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/errno.h>
@@ -65,18 +68,13 @@ struct rtl8366rb_softc {
int smi_acquired; /* serialize access to SMI/I2C bus */
struct mtx callout_mtx; /* serialize callout */
device_t dev;
- int vid[RTL8366RB_NUM_VLANS];
- char *ifname[RTL8366RB_NUM_PHYS];
- device_t miibus[RTL8366RB_NUM_PHYS];
- struct ifnet *ifp[RTL8366RB_NUM_PHYS];
+ int vid[RTL8366_NUM_VLANS];
+ char *ifname[RTL8366_NUM_PHYS];
+ device_t miibus[RTL8366_NUM_PHYS];
+ struct ifnet *ifp[RTL8366_NUM_PHYS];
struct callout callout_tick;
-};
-
-static etherswitch_info_t etherswitch_info = {
- .es_nports = RTL8366RB_NUM_PORTS,
- .es_nvlangroups = RTL8366RB_NUM_VLANS,
- .es_name = "Realtek RTL8366RB",
- .es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q,
+ etherswitch_info_t info;
+ int chip_type; /* 0 = RTL8366RB, 1 = RTL8366SR */
};
#define RTL_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
@@ -133,77 +131,101 @@ rtl8366rb_identify(driver_t *driver, device_t parent)
if (device_find_child(parent, "rtl8366rb", -1) == NULL) {
child = BUS_ADD_CHILD(parent, 0, "rtl8366rb", -1);
devi = IICBUS_IVAR(child);
- devi->addr = RTL8366RB_IIC_ADDR;
+ devi->addr = RTL8366_IIC_ADDR;
}
}
static int
rtl8366rb_probe(device_t dev)
{
+ struct rtl8366rb_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ bzero(sc, sizeof(*sc));
if (smi_probe(dev) != 0)
return (ENXIO);
- device_set_desc(dev, "RTL8366RB Ethernet Switch Controller");
+ if(sc->chip_type == 0)
+ device_set_desc(dev, "RTL8366RB Ethernet Switch Controller");
+ else
+ device_set_desc(dev, "RTL8366SR Ethernet Switch Controller");
return (BUS_PROBE_DEFAULT);
}
static void
rtl8366rb_init(device_t dev)
{
- int i;
struct rtl8366rb_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
/* Initialisation for TL-WR1043ND */
- smi_rmw(dev, RTL8366RB_RCR,
- RTL8366RB_RCR_HARD_RESET,
- RTL8366RB_RCR_HARD_RESET, RTL_WAITOK);
+#ifdef RTL8366_SOFT_RESET
+ smi_rmw(dev, RTL8366_RCR,
+ RTL8366_RCR_SOFT_RESET,
+ RTL8366_RCR_SOFT_RESET, RTL_WAITOK);
+#else
+ smi_rmw(dev, RTL8366_RCR,
+ RTL8366_RCR_HARD_RESET,
+ RTL8366_RCR_HARD_RESET, RTL_WAITOK);
+#endif
+ /* hard reset not return ack */
DELAY(100000);
/* Enable 16 VLAN mode */
- smi_rmw(dev, RTL8366RB_SGCR,
- RTL8366RB_SGCR_EN_VLAN | RTL8366RB_SGCR_EN_VLAN_4KTB,
- RTL8366RB_SGCR_EN_VLAN, RTL_WAITOK);
+ smi_rmw(dev, RTL8366_SGCR,
+ RTL8366_SGCR_EN_VLAN | RTL8366_SGCR_EN_VLAN_4KTB,
+ RTL8366_SGCR_EN_VLAN, RTL_WAITOK);
/* Initialize our vlan table. */
- sc = device_get_softc(dev);
for (i = 0; i <= 1; i++)
sc->vid[i] = (i + 1) | ETHERSWITCH_VID_VALID;
/* Remove port 0 from VLAN 1. */
- smi_rmw(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, 0),
+ smi_rmw(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, 0),
(1 << 0), 0, RTL_WAITOK);
/* Add port 0 untagged and port 5 tagged to VLAN 2. */
- smi_rmw(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, 1),
- ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_MEMBER_SHIFT)
- | ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_UNTAG_SHIFT),
- ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_MEMBER_SHIFT
- | ((1 << 0) << RTL8366RB_VMCR_MU_UNTAG_SHIFT)),
+ smi_rmw(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, 1),
+ ((1 << 5 | 1 << 0) << RTL8366_VMCR_MU_MEMBER_SHIFT)
+ | ((1 << 5 | 1 << 0) << RTL8366_VMCR_MU_UNTAG_SHIFT),
+ ((1 << 5 | 1 << 0) << RTL8366_VMCR_MU_MEMBER_SHIFT
+ | ((1 << 0) << RTL8366_VMCR_MU_UNTAG_SHIFT)),
RTL_WAITOK);
/* Set PVID 2 for port 0. */
- smi_rmw(dev, RTL8366RB_PVCR_REG(0),
- RTL8366RB_PVCR_VAL(0, RTL8366RB_PVCR_PORT_MASK),
- RTL8366RB_PVCR_VAL(0, 1), RTL_WAITOK);
+ smi_rmw(dev, RTL8366_PVCR_REG(0),
+ RTL8366_PVCR_VAL(0, RTL8366_PVCR_PORT_MASK),
+ RTL8366_PVCR_VAL(0, 1), RTL_WAITOK);
}
static int
rtl8366rb_attach(device_t dev)
{
- uint16_t rev = 0;
struct rtl8366rb_softc *sc;
+ uint16_t rev = 0;
char name[IFNAMSIZ];
int err = 0;
int i;
sc = device_get_softc(dev);
- bzero(sc, sizeof(*sc));
+
sc->dev = dev;
mtx_init(&sc->sc_mtx, "rtl8366rb", NULL, MTX_DEF);
sc->smi_acquired = 0;
mtx_init(&sc->callout_mtx, "rtl8366rbcallout", NULL, MTX_DEF);
rtl8366rb_init(dev);
- smi_read(dev, RTL8366RB_CVCR, &rev, RTL_WAITOK);
+ smi_read(dev, RTL8366_CVCR, &rev, RTL_WAITOK);
device_printf(dev, "rev. %d\n", rev & 0x000f);
+ sc->info.es_nports = RTL8366_NUM_PORTS;
+ sc->info.es_nvlangroups = RTL8366_NUM_VLANS;
+ sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q;
+ if(sc->chip_type == 0)
+ sprintf(sc->info.es_name, "Realtek RTL8366RB");
+ else
+ sprintf(sc->info.es_name, "Realtek RTL8366SR");
+
/* attach miibus and phys */
/* PHYs need an interface, so we generate a dummy one */
- for (i = 0; i < RTL8366RB_NUM_PHYS; i++) {
+ for (i = 0; i < RTL8366_NUM_PHYS; i++) {
sc->ifp[i] = if_alloc(IFT_ETHER);
sc->ifp[i]->if_softc = sc;
sc->ifp[i]->if_flags |= IFF_UP | IFF_BROADCAST | IFF_DRV_RUNNING
@@ -236,10 +258,12 @@ rtl8366rb_attach(device_t dev)
static int
rtl8366rb_detach(device_t dev)
{
- struct rtl8366rb_softc *sc = device_get_softc(dev);
+ struct rtl8366rb_softc *sc;
int i;
- for (i=0; i < RTL8366RB_NUM_PHYS; i++) {
+ sc = device_get_softc(dev);
+
+ for (i=0; i < RTL8366_NUM_PHYS; i++) {
if (sc->miibus[i])
device_delete_child(dev, sc->miibus[i]);
if (sc->ifp[i] != NULL)
@@ -259,30 +283,30 @@ rtl8366rb_update_ifmedia(int portstatus, u_int *media_status, u_int *media_activ
{
*media_active = IFM_ETHER;
*media_status = IFM_AVALID;
- if ((portstatus & RTL8366RB_PLSR_LINK) != 0)
+ if ((portstatus & RTL8366_PLSR_LINK) != 0)
*media_status |= IFM_ACTIVE;
else {
*media_active |= IFM_NONE;
return;
}
- switch (portstatus & RTL8366RB_PLSR_SPEED_MASK) {
- case RTL8366RB_PLSR_SPEED_10:
+ switch (portstatus & RTL8366_PLSR_SPEED_MASK) {
+ case RTL8366_PLSR_SPEED_10:
*media_active |= IFM_10_T;
break;
- case RTL8366RB_PLSR_SPEED_100:
+ case RTL8366_PLSR_SPEED_100:
*media_active |= IFM_100_TX;
break;
- case RTL8366RB_PLSR_SPEED_1000:
+ case RTL8366_PLSR_SPEED_1000:
*media_active |= IFM_1000_T;
break;
}
- if ((portstatus & RTL8366RB_PLSR_FULLDUPLEX) != 0)
+ if ((portstatus & RTL8366_PLSR_FULLDUPLEX) != 0)
*media_active |= IFM_FDX;
else
*media_active |= IFM_HDX;
- if ((portstatus & RTL8366RB_PLSR_TXPAUSE) != 0)
+ if ((portstatus & RTL8366_PLSR_TXPAUSE) != 0)
*media_active |= IFM_ETH_TXPAUSE;
- if ((portstatus & RTL8366RB_PLSR_RXPAUSE) != 0)
+ if ((portstatus & RTL8366_PLSR_RXPAUSE) != 0)
*media_active |= IFM_ETH_RXPAUSE;
}
@@ -295,10 +319,10 @@ rtl833rb_miipollstat(struct rtl8366rb_softc *sc)
uint16_t value;
int portstatus;
- for (i = 0; i < RTL8366RB_NUM_PHYS; i++) {
+ for (i = 0; i < RTL8366_NUM_PHYS; i++) {
mii = device_get_softc(sc->miibus[i]);
if ((i % 2) == 0) {
- if (smi_read(sc->dev, RTL8366RB_PLSR_BASE + i/2, &value, RTL_NOWAIT) != 0) {
+ if (smi_read(sc->dev, RTL8366_PLSR_BASE + i/2, &value, RTL_NOWAIT) != 0) {
DEBUG_INCRVAR(callout_blocked);
return;
}
@@ -318,7 +342,9 @@ rtl833rb_miipollstat(struct rtl8366rb_softc *sc)
static void
rtl8366rb_tick(void *arg)
{
- struct rtl8366rb_softc *sc = arg;
+ struct rtl8366rb_softc *sc;
+
+ sc = arg;
rtl833rb_miipollstat(sc);
callout_reset(&sc->callout_tick, hz, rtl8366rb_tick, sc);
@@ -327,39 +353,65 @@ rtl8366rb_tick(void *arg)
static int
smi_probe(device_t dev)
{
+ struct rtl8366rb_softc *sc;
device_t iicbus, iicha;
- int err, i;
+ int err, i, j;
uint16_t chipid;
char bytes[2];
int xferd;
- bytes[0] = RTL8366RB_CIR & 0xff;
- bytes[1] = (RTL8366RB_CIR >> 8) & 0xff;
+ sc = device_get_softc(dev);
+
iicbus = device_get_parent(dev);
iicha = device_get_parent(iicbus);
- iicbus_reset(iicbus, IIC_FASTEST, RTL8366RB_IIC_ADDR, NULL);
- for (i=3; i--; ) {
- IICBUS_STOP(iicha);
- /*
- * we go directly to the host adapter because iicbus.c
- * only issues a stop on a bus that was successfully started.
- */
+
+ for(i = 0; i < 2; ++i) {
+ iicbus_reset(iicbus, IIC_FASTEST, RTL8366_IIC_ADDR, NULL);
+ for (j=3; j--; ) {
+ IICBUS_STOP(iicha);
+ /*
+ * we go directly to the host adapter because iicbus.c
+ * only issues a stop on a bus that was successfully started.
+ */
+ }
+ err = iicbus_request_bus(iicbus, dev, IIC_WAIT);
+ if (err != 0)
+ goto out;
+ err = iicbus_start(iicbus, RTL8366_IIC_ADDR | RTL_IICBUS_READ, RTL_IICBUS_TIMEOUT);
+ if (err != 0)
+ goto out;
+ if(i == 0) {
+ bytes[0] = RTL8366RB_CIR & 0xff;
+ bytes[1] = (RTL8366RB_CIR >> 8) & 0xff;
+ } else {
+ bytes[0] = RTL8366SR_CIR & 0xff;
+ bytes[1] = (RTL8366SR_CIR >> 8) & 0xff;
+ }
+ err = iicbus_write(iicbus, bytes, 2, &xferd, RTL_IICBUS_TIMEOUT);
+ if (err != 0)
+ goto out;
+ err = iicbus_read(iicbus, bytes, 2, &xferd, IIC_LAST_READ, 0);
+ if (err != 0)
+ goto out;
+ chipid = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff);
+ if (i == 0 && chipid == RTL8366RB_CIR_ID8366RB) {
+ DPRINTF(dev, "chip id 0x%04x\n", chipid);
+ sc->chip_type = 0;
+ err = 0;
+ break;
+ }
+ if (i == 1 && chipid == RTL8366SR_CIR_ID8366SR) {
+ DPRINTF(dev, "chip id 0x%04x\n", chipid);
+ sc->chip_type = 1;
+ err = 0;
+ break;
+ }
+ if(i == 0) {
+ iicbus_stop(iicbus);
+ iicbus_release_bus(iicbus, dev);
+ }
}
- err = iicbus_request_bus(iicbus, dev, IIC_WAIT);
- if (err != 0)
- goto out;
- err = iicbus_start(iicbus, RTL8366RB_IIC_ADDR | RTL_IICBUS_READ, RTL_IICBUS_TIMEOUT);
- if (err != 0)
- goto out;
- err = iicbus_write(iicbus, bytes, 2, &xferd, RTL_IICBUS_TIMEOUT);
- if (err != 0)
- goto out;
- err = iicbus_read(iicbus, bytes, 2, &xferd, IIC_LAST_READ, 0);
- if (err != 0)
- goto out;
- chipid = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff);
- DPRINTF(dev, "chip id 0x%04x\n", chipid);
- if (chipid != RTL8366RB_CIR_ID8366RB)
+ if(i == 2)
err = ENXIO;
out:
iicbus_stop(iicbus);
@@ -406,12 +458,25 @@ smi_release(struct rtl8366rb_softc *sc, int sleep)
static int
smi_select(device_t dev, int op, int sleep)
{
+ struct rtl8366rb_softc *sc;
int err, i;
- device_t iicbus = device_get_parent(dev);
- struct iicbus_ivar *devi = IICBUS_IVAR(dev);
- int slave = devi->addr;
+ device_t iicbus;
+ struct iicbus_ivar *devi;
+ int slave;
+
+ sc = device_get_softc(dev);
+
+ iicbus = device_get_parent(dev);
+ devi = IICBUS_IVAR(dev);
+ slave = devi->addr;
RTL_SMI_ACQUIRED_ASSERT((struct rtl8366rb_softc *)device_get_softc(dev));
+
+ if(sc->chip_type == 1) { // RTL8366SR work around
+ // this is same work around at probe
+ for (int i=3; i--; )
+ IICBUS_STOP(device_get_parent(device_get_parent(dev)));
+ }
/*
* The chip does not use clock stretching when it is busy,
* instead ignoring the command. Retry a few times.
@@ -433,10 +498,12 @@ static int
smi_read_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t *data, int sleep)
{
int err;
- device_t iicbus = device_get_parent(sc->dev);
+ device_t iicbus;
char bytes[2];
int xferd;
+ iicbus = device_get_parent(sc->dev);
+
RTL_SMI_ACQUIRED_ASSERT(sc);
bytes[0] = addr & 0xff;
bytes[1] = (addr >> 8) & 0xff;
@@ -460,10 +527,12 @@ static int
smi_write_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t data, int sleep)
{
int err;
- device_t iicbus = device_get_parent(sc->dev);
+ device_t iicbus;
char bytes[4];
int xferd;
+ iicbus = device_get_parent(sc->dev);
+
RTL_SMI_ACQUIRED_ASSERT(sc);
bytes[0] = addr & 0xff;
bytes[1] = (addr >> 8) & 0xff;
@@ -481,9 +550,11 @@ smi_write_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t data, int s
static int
smi_read(device_t dev, uint16_t addr, uint16_t *data, int sleep)
{
- struct rtl8366rb_softc *sc = device_get_softc(dev);
+ struct rtl8366rb_softc *sc;
int err;
+ sc = device_get_softc(dev);
+
err = smi_acquire(sc, sleep);
if (err != 0)
return (EBUSY);
@@ -496,9 +567,11 @@ smi_read(device_t dev, uint16_t addr, uint16_t *data, int sleep)
static int
smi_write(device_t dev, uint16_t addr, uint16_t data, int sleep)
{
- struct rtl8366rb_softc *sc = device_get_softc(dev);
+ struct rtl8366rb_softc *sc;
int err;
+ sc = device_get_softc(dev);
+
err = smi_acquire(sc, sleep);
if (err != 0)
return (EBUSY);
@@ -511,10 +584,12 @@ smi_write(device_t dev, uint16_t addr, uint16_t data, int sleep)
static int
smi_rmw(device_t dev, uint16_t addr, uint16_t mask, uint16_t data, int sleep)
{
- struct rtl8366rb_softc *sc = device_get_softc(dev);
+ struct rtl8366rb_softc *sc;
int err;
uint16_t oldv, newv;
+ sc = device_get_softc(dev);
+
err = smi_acquire(sc, sleep);
if (err != 0)
return (EBUSY);
@@ -535,13 +610,19 @@ smi_rmw(device_t dev, uint16_t addr, uint16_t mask, uint16_t data, int sleep)
static etherswitch_info_t *
rtl_getinfo(device_t dev)
{
- return (&etherswitch_info);
+ struct rtl8366rb_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return (&sc->info);
}
static int
rtl_readreg(device_t dev, int reg)
{
- uint16_t data = 0;
+ uint16_t data;
+
+ data = 0;
smi_read(dev, reg, &data, RTL_WAITOK);
return (data);
@@ -559,18 +640,21 @@ rtl_getport(device_t dev, etherswitch_port_t *p)
struct rtl8366rb_softc *sc;
struct ifmedia *ifm;
struct mii_data *mii;
- struct ifmediareq *ifmr = &p->es_ifmr;
+ struct ifmediareq *ifmr;
uint16_t v;
int err, vlangroup;
- if (p->es_port < 0 || p->es_port >= RTL8366RB_NUM_PORTS)
- return (ENXIO);
sc = device_get_softc(dev);
- vlangroup = RTL8366RB_PVCR_GET(p->es_port,
- rtl_readreg(dev, RTL8366RB_PVCR_REG(p->es_port)));
+
+ ifmr = &p->es_ifmr;
+
+ if (p->es_port < 0 || p->es_port >= RTL8366_NUM_PORTS)
+ return (ENXIO);
+ vlangroup = RTL8366_PVCR_GET(p->es_port,
+ rtl_readreg(dev, RTL8366_PVCR_REG(p->es_port)));
p->es_pvid = sc->vid[vlangroup] & ETHERSWITCH_VID_MASK;
- if (p->es_port < RTL8366RB_NUM_PHYS) {
+ if (p->es_port < RTL8366_NUM_PHYS) {
mii = device_get_softc(sc->miibus[p->es_port]);
ifm = &mii->mii_media;
err = ifmedia_ioctl(sc->ifp[p->es_port], &p->es_ifr, ifm, SIOCGIFMEDIA);
@@ -579,8 +663,8 @@ rtl_getport(device_t dev, etherswitch_port_t *p)
} else {
/* fill in fixed values for CPU port */
p->es_flags |= ETHERSWITCH_PORT_CPU;
- smi_read(dev, RTL8366RB_PLSR_BASE + (RTL8366RB_NUM_PHYS)/2, &v, RTL_WAITOK);
- v = v >> (8 * ((RTL8366RB_NUM_PHYS) % 2));
+ smi_read(dev, RTL8366_PLSR_BASE + (RTL8366_NUM_PHYS)/2, &v, RTL_WAITOK);
+ v = v >> (8 * ((RTL8366_NUM_PHYS) % 2));
rtl8366rb_update_ifmedia(v, &ifmr->ifm_status, &ifmr->ifm_active);
ifmr->ifm_current = ifmr->ifm_active;
ifmr->ifm_mask = 0;
@@ -599,16 +683,17 @@ rtl_getport(device_t dev, etherswitch_port_t *p)
static int
rtl_setport(device_t dev, etherswitch_port_t *p)
{
- int i, err, vlangroup;
struct rtl8366rb_softc *sc;
+ int i, err, vlangroup;
struct ifmedia *ifm;
struct mii_data *mii;
- if (p->es_port < 0 || p->es_port >= RTL8366RB_NUM_PORTS)
- return (ENXIO);
sc = device_get_softc(dev);
+
+ if (p->es_port < 0 || p->es_port >= RTL8366_NUM_PORTS)
+ return (ENXIO);
vlangroup = -1;
- for (i = 0; i < RTL8366RB_NUM_VLANS; i++) {
+ for (i = 0; i < RTL8366_NUM_VLANS; i++) {
if ((sc->vid[i] & ETHERSWITCH_VID_MASK) == p->es_pvid) {
vlangroup = i;
break;
@@ -616,12 +701,12 @@ rtl_setport(device_t dev, etherswitch_port_t *p)
}
if (vlangroup == -1)
return (ENXIO);
- err = smi_rmw(dev, RTL8366RB_PVCR_REG(p->es_port),
- RTL8366RB_PVCR_VAL(p->es_port, RTL8366RB_PVCR_PORT_MASK),
- RTL8366RB_PVCR_VAL(p->es_port, vlangroup), RTL_WAITOK);
+ err = smi_rmw(dev, RTL8366_PVCR_REG(p->es_port),
+ RTL8366_PVCR_VAL(p->es_port, RTL8366_PVCR_PORT_MASK),
+ RTL8366_PVCR_VAL(p->es_port, vlangroup), RTL_WAITOK);
if (err)
return (err);
- if (p->es_port == RTL8366RB_CPU_PORT)
+ if (p->es_port == RTL8366_CPU_PORT)
return (0);
mii = device_get_softc(sc->miibus[p->es_port]);
ifm = &mii->mii_media;
@@ -636,14 +721,15 @@ rtl_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
uint16_t vmcr[3];
int i;
- for (i=0; i<3; i++)
- vmcr[i] = rtl_readreg(dev, RTL8366RB_VMCR(i, vg->es_vlangroup));
-
sc = device_get_softc(dev);
+
+ for (i=0; i<RTL8366_VMCR_MULT; i++)
+ vmcr[i] = rtl_readreg(dev, RTL8366_VMCR(i, vg->es_vlangroup));
+
vg->es_vid = sc->vid[vg->es_vlangroup];
- vg->es_member_ports = RTL8366RB_VMCR_MEMBER(vmcr);
- vg->es_untagged_ports = RTL8366RB_VMCR_UNTAG(vmcr);
- vg->es_fid = RTL8366RB_VMCR_FID(vmcr);
+ vg->es_member_ports = RTL8366_VMCR_MEMBER(vmcr);
+ vg->es_untagged_ports = RTL8366_VMCR_UNTAG(vmcr);
+ vg->es_fid = RTL8366_VMCR_FID(vmcr);
return (0);
}
@@ -651,21 +737,31 @@ static int
rtl_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
{
struct rtl8366rb_softc *sc;
- int g = vg->es_vlangroup;
+ int g;
sc = device_get_softc(dev);
+
+ g = vg->es_vlangroup;
+
sc->vid[g] = vg->es_vid;
/* VLAN group disabled ? */
if (vg->es_member_ports == 0 && vg->es_untagged_ports == 0 && vg->es_vid == 0)
return (0);
sc->vid[g] |= ETHERSWITCH_VID_VALID;
- rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_DOT1Q_REG, g),
- (vg->es_vid << RTL8366RB_VMCR_DOT1Q_VID_SHIFT) & RTL8366RB_VMCR_DOT1Q_VID_MASK);
- rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, g),
- ((vg->es_member_ports << RTL8366RB_VMCR_MU_MEMBER_SHIFT) & RTL8366RB_VMCR_MU_MEMBER_MASK) |
- ((vg->es_untagged_ports << RTL8366RB_VMCR_MU_UNTAG_SHIFT) & RTL8366RB_VMCR_MU_UNTAG_MASK));
- rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_FID_REG, g),
- vg->es_fid);
+ rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_DOT1Q_REG, g),
+ (vg->es_vid << RTL8366_VMCR_DOT1Q_VID_SHIFT) & RTL8366_VMCR_DOT1Q_VID_MASK);
+ if(sc->chip_type == 0) {
+ rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, g),
+ ((vg->es_member_ports << RTL8366_VMCR_MU_MEMBER_SHIFT) & RTL8366_VMCR_MU_MEMBER_MASK) |
+ ((vg->es_untagged_ports << RTL8366_VMCR_MU_UNTAG_SHIFT) & RTL8366_VMCR_MU_UNTAG_MASK));
+ rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_FID_REG, g),
+ vg->es_fid);
+ } else {
+ rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, g),
+ ((vg->es_member_ports << RTL8366_VMCR_MU_MEMBER_SHIFT) & RTL8366_VMCR_MU_MEMBER_MASK) |
+ ((vg->es_untagged_ports << RTL8366_VMCR_MU_UNTAG_SHIFT) & RTL8366_VMCR_MU_UNTAG_MASK) |
+ ((vg->es_fid << RTL8366_VMCR_FID_FID_SHIFT) & RTL8366_VMCR_FID_FID_MASK));
+ }
return (0);
}
@@ -683,24 +779,28 @@ rtl_getconf(device_t dev, etherswitch_conf_t *conf)
static int
rtl_readphy(device_t dev, int phy, int reg)
{
- struct rtl8366rb_softc *sc = device_get_softc(dev);
- uint16_t data = 0;
+ struct rtl8366rb_softc *sc;
+ uint16_t data;
int err, i, sleep;
- if (phy < 0 || phy >= RTL8366RB_NUM_PHYS)
+ sc = device_get_softc(dev);
+
+ data = 0;
+
+ if (phy < 0 || phy >= RTL8366_NUM_PHYS)
return (ENXIO);
- if (reg < 0 || reg >= RTL8366RB_NUM_PHY_REG)
+ if (reg < 0 || reg >= RTL8366_NUM_PHY_REG)
return (ENXIO);
sleep = RTL_WAITOK;
err = smi_acquire(sc, sleep);
if (err != 0)
return (EBUSY);
for (i = RTL_IICBUS_RETRIES; i--; ) {
- err = smi_write_locked(sc, RTL8366RB_PACR, RTL8366RB_PACR_READ, sleep);
+ err = smi_write_locked(sc, RTL8366_PACR, RTL8366_PACR_READ, sleep);
if (err == 0)
- err = smi_write_locked(sc, RTL8366RB_PHYREG(phy, 0, reg), 0, sleep);
+ err = smi_write_locked(sc, RTL8366_PHYREG(phy, 0, reg), 0, sleep);
if (err == 0) {
- err = smi_read_locked(sc, RTL8366RB_PADR, &data, sleep);
+ err = smi_read_locked(sc, RTL8366_PADR, &data, sleep);
break;
}
DEBUG_INCRVAR(phy_access_retries);
@@ -715,21 +815,23 @@ rtl_readphy(device_t dev, int phy, int reg)
static int
rtl_writephy(device_t dev, int phy, int reg, int data)
{
- struct rtl8366rb_softc *sc = device_get_softc(dev);
+ struct rtl8366rb_softc *sc;
int err, i, sleep;
- if (phy < 0 || phy >= RTL8366RB_NUM_PHYS)
+ sc = device_get_softc(dev);
+
+ if (phy < 0 || phy >= RTL8366_NUM_PHYS)
return (ENXIO);
- if (reg < 0 || reg >= RTL8366RB_NUM_PHY_REG)
+ if (reg < 0 || reg >= RTL8366_NUM_PHY_REG)
return (ENXIO);
sleep = RTL_WAITOK;
err = smi_acquire(sc, sleep);
if (err != 0)
return (EBUSY);
for (i = RTL_IICBUS_RETRIES; i--; ) {
- err = smi_write_locked(sc, RTL8366RB_PACR, RTL8366RB_PACR_WRITE, sleep);
+ err = smi_write_locked(sc, RTL8366_PACR, RTL8366_PACR_WRITE, sleep);
if (err == 0)
- err = smi_write_locked(sc, RTL8366RB_PHYREG(phy, 0, reg), data, sleep);
+ err = smi_write_locked(sc, RTL8366_PHYREG(phy, 0, reg), data, sleep);
if (err == 0) {
break;
}
@@ -745,8 +847,11 @@ rtl_writephy(device_t dev, int phy, int reg, int data)
static int
rtl8366rb_ifmedia_upd(struct ifnet *ifp)
{
- struct rtl8366rb_softc *sc = ifp->if_softc;
- struct mii_data *mii = device_get_softc(sc->miibus[ifp->if_dunit]);
+ struct rtl8366rb_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = device_get_softc(sc->miibus[ifp->if_dunit]);
mii_mediachg(mii);
return (0);
@@ -755,8 +860,11 @@ rtl8366rb_ifmedia_upd(struct ifnet *ifp)
static void
rtl8366rb_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
- struct rtl8366rb_softc *sc = ifp->if_softc;
- struct mii_data *mii = device_get_softc(sc->miibus[ifp->if_dunit]);
+ struct rtl8366rb_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = device_get_softc(sc->miibus[ifp->if_dunit]);
mii_pollstat(mii);
ifmr->ifm_active = mii->mii_media_active;
diff --git a/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h b/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h
index 09037059264d..66ca0ad245ee 100644
--- a/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h
+++ b/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2015-2016 Hiroki Mori.
* Copyright (c) 2011-2012 Stefan Bethke.
* All rights reserved.
*
@@ -29,7 +30,7 @@
#ifndef _DEV_ETHERSWITCH_RTL8366RBVAR_H_
#define _DEV_ETHERSWITCH_RTL8366RBVAR_H_
-#define RTL8366RB_IIC_ADDR 0xa8
+#define RTL8366_IIC_ADDR 0xa8
#define RTL_IICBUS_TIMEOUT 100 /* us */
#define RTL_IICBUS_READ 1
#define RTL_IICBUS_WRITE 0
@@ -40,138 +41,142 @@
/* Register definitions */
/* Switch Global Configuration */
-#define RTL8366RB_SGCR 0x0000
-#define RTL8366RB_SGCR_EN_BC_STORM_CTRL 0x0001
-#define RTL8366RB_SGCR_MAX_LENGTH_MASK 0x0030
-#define RTL8366RB_SGCR_MAX_LENGTH_1522 0x0000
-#define RTL8366RB_SGCR_MAX_LENGTH_1536 0x0010
-#define RTL8366RB_SGCR_MAX_LENGTH_1552 0x0020
-#define RTL8366RB_SGCR_MAX_LENGTH_9216 0x0030
-#define RTL8366RB_SGCR_EN_VLAN 0x2000
-#define RTL8366RB_SGCR_EN_VLAN_4KTB 0x4000
-#define RTL8366RB_SGCR_EN_QOS 0x8000
+#define RTL8366_SGCR 0x0000
+#define RTL8366_SGCR_EN_BC_STORM_CTRL 0x0001
+#define RTL8366_SGCR_MAX_LENGTH_MASK 0x0030
+#define RTL8366_SGCR_MAX_LENGTH_1522 0x0000
+#define RTL8366_SGCR_MAX_LENGTH_1536 0x0010
+#define RTL8366_SGCR_MAX_LENGTH_1552 0x0020
+#define RTL8366_SGCR_MAX_LENGTH_9216 0x0030
+#define RTL8366_SGCR_EN_VLAN 0x2000
+#define RTL8366_SGCR_EN_VLAN_4KTB 0x4000
+#define RTL8366_SGCR_EN_QOS 0x8000
/* Port Enable Control: DISABLE_PORT[5:0] */
-#define RTL8366RB_PECR 0x0001
+#define RTL8366_PECR 0x0001
/* Switch Security Control 0: DIS_LEARN[5:0] */
-#define RTL8366RB_SSCR0 0x0002
+#define RTL8366_SSCR0 0x0002
/* Switch Security Control 1: DIS_AGE[5:0] */
-#define RTL8366RB_SSCR1 0x0003
+#define RTL8366_SSCR1 0x0003
/* Switch Security Control 2 */
-#define RTL8366RB_SSCR2 0x0004
-#define RTL8366RB_SSCR2_DROP_UNKNOWN_DA 0x0001
+#define RTL8366_SSCR2 0x0004
+#define RTL8366_SSCR2_DROP_UNKNOWN_DA 0x0001
/* Port Link Status: two ports per register */
-#define RTL8366RB_PLSR_BASE 0x0014
-#define RTL8366RB_PLSR_SPEED_MASK 0x03
-#define RTL8366RB_PLSR_SPEED_10 0x00
-#define RTL8366RB_PLSR_SPEED_100 0x01
-#define RTL8366RB_PLSR_SPEED_1000 0x02
-#define RTL8366RB_PLSR_FULLDUPLEX 0x04
-#define RTL8366RB_PLSR_LINK 0x10
-#define RTL8366RB_PLSR_TXPAUSE 0x20
-#define RTL8366RB_PLSR_RXPAUSE 0x40
-#define RTL8366RB_PLSR_NO_AUTO 0x80
-
-/* VLAN Member Configuration, 3 registers per VLAN */
-#define RTL8366RB_VMCR_BASE 0x0020
-#define RTL8366RB_VMCR_MULT 3
-#define RTL8366RB_VMCR_DOT1Q_REG 0
-#define RTL8366RB_VMCR_DOT1Q_VID_SHIFT 0
-#define RTL8366RB_VMCR_DOT1Q_VID_MASK 0x0fff
-#define RTL8366RB_VMCR_DOT1Q_PCP_SHIFT 12
-#define RTL8366RB_VMCR_DOT1Q_PCP_MASK 0x7000
-#define RTL8366RB_VMCR_MU_REG 1
-#define RTL8366RB_VMCR_MU_MEMBER_SHIFT 0
-#define RTL8366RB_VMCR_MU_MEMBER_MASK 0x00ff
-#define RTL8366RB_VMCR_MU_UNTAG_SHIFT 8
-#define RTL8366RB_VMCR_MU_UNTAG_MASK 0xff00
-#define RTL8366RB_VMCR_FID_REG 2
-#define RTL8366RB_VMCR_FID_FID_SHIFT 0
-#define RTL8366RB_VMCR_FID_FID_MASK 0x0007
-#define RTL8366RB_VMCR(_reg, _vlan) \
- (RTL8366RB_VMCR_BASE + _reg + _vlan * RTL8366RB_VMCR_MULT)
+#define RTL8366_PLSR_BASE (sc->chip_type == 0 ? 0x0014 : 0x0060)
+#define RTL8366_PLSR_SPEED_MASK 0x03
+#define RTL8366_PLSR_SPEED_10 0x00
+#define RTL8366_PLSR_SPEED_100 0x01
+#define RTL8366_PLSR_SPEED_1000 0x02
+#define RTL8366_PLSR_FULLDUPLEX 0x04
+#define RTL8366_PLSR_LINK 0x10
+#define RTL8366_PLSR_TXPAUSE 0x20
+#define RTL8366_PLSR_RXPAUSE 0x40
+#define RTL8366_PLSR_NO_AUTO 0x80
+
+/* VLAN Member Configuration, 3 or 2 registers per VLAN */
+#define RTL8366_VMCR_BASE (sc->chip_type == 0 ? 0x0020 : 0x0016)
+#define RTL8366_VMCR_MULT (sc->chip_type == 0 ? 3 : 2)
+#define RTL8366_VMCR_DOT1Q_REG 0
+#define RTL8366_VMCR_DOT1Q_VID_SHIFT 0
+#define RTL8366_VMCR_DOT1Q_VID_MASK 0x0fff
+#define RTL8366_VMCR_DOT1Q_PCP_SHIFT 12
+#define RTL8366_VMCR_DOT1Q_PCP_MASK 0x7000
+#define RTL8366_VMCR_MU_REG 1
+#define RTL8366_VMCR_MU_MEMBER_SHIFT 0
+#define RTL8366_VMCR_MU_MEMBER_MASK (sc->chip_type == 0 ? 0x00ff : 0x003f)
+#define RTL8366_VMCR_MU_UNTAG_SHIFT (sc->chip_type == 0 ? 8 : 6)
+#define RTL8366_VMCR_MU_UNTAG_MASK (sc->chip_type == 0 ? 0xff00 : 0x0fc0)
+#define RTL8366_VMCR_FID_REG (sc->chip_type == 0 ? 2 : 1)
+#define RTL8366_VMCR_FID_FID_SHIFT (sc->chip_type == 0 ? 0 : 12)
+#define RTL8366_VMCR_FID_FID_MASK (sc->chip_type == 0 ? 0x0007 : 0x7000)
+#define RTL8366_VMCR(_reg, _vlan) \
+ (RTL8366_VMCR_BASE + _reg + _vlan * RTL8366_VMCR_MULT)
/* VLAN Identifier */
-#define RTL8366RB_VMCR_VID(_r) \
- (_r[RTL8366RB_VMCR_DOT1Q_REG] & RTL8366RB_VMCR_DOT1Q_VID_MASK)
+#define RTL8366_VMCR_VID(_r) \
+ (_r[RTL8366_VMCR_DOT1Q_REG] & RTL8366_VMCR_DOT1Q_VID_MASK)
/* Priority Code Point */
-#define RTL8366RB_VMCR_PCP(_r) \
- ((_r[RTL8366RB_VMCR_DOT1Q_REG] & RTL8366RB_VMCR_DOT1Q_PCP_MASK) \
- >> RTL8366RB_VMCR_DOT1Q_PCP_SHIFT)
+#define RTL8366_VMCR_PCP(_r) \
+ ((_r[RTL8366_VMCR_DOT1Q_REG] & RTL8366_VMCR_DOT1Q_PCP_MASK) \
+ >> RTL8366_VMCR_DOT1Q_PCP_SHIFT)
/* Member ports */
-#define RTL8366RB_VMCR_MEMBER(_r) \
- (_r[RTL8366RB_VMCR_MU_REG] & RTL8366RB_VMCR_MU_MEMBER_MASK)
+#define RTL8366_VMCR_MEMBER(_r) \
+ (_r[RTL8366_VMCR_MU_REG] & RTL8366_VMCR_MU_MEMBER_MASK)
/* Untagged ports */
-#define RTL8366RB_VMCR_UNTAG(_r) \
- ((_r[RTL8366RB_VMCR_MU_REG] & RTL8366RB_VMCR_MU_UNTAG_MASK) \
- >> RTL8366RB_VMCR_MU_UNTAG_SHIFT)
+#define RTL8366_VMCR_UNTAG(_r) \
+ ((_r[RTL8366_VMCR_MU_REG] & RTL8366_VMCR_MU_UNTAG_MASK) \
+ >> RTL8366_VMCR_MU_UNTAG_SHIFT)
/* Forwarding ID */
-#define RTL8366RB_VMCR_FID(_r) \
- (_r[RTL8366RB_VMCR_FID_REG] & RTL8366RB_VMCR_FID_FID_MASK)
+#define RTL8366_VMCR_FID(_r) \
+ (sc->chip_type == 0 ? (_r[RTL8366_VMCR_FID_REG] & RTL8366_VMCR_FID_FID_MASK) : \
+ ((_r[RTL8366_VMCR_FID_REG] & RTL8366_VMCR_FID_FID_MASK) \
+ >> RTL8366_VMCR_FID_FID_SHIFT))
/*
* Port VLAN Control, 4 ports per register
* Determines the VID for untagged ingress frames through
* index into VMC.
*/
-#define RTL8366RB_PVCR_BASE 0x0063
-#define RTL8366RB_PVCR_PORT_SHIFT 4
-#define RTL8366RB_PVCR_PORT_PERREG (16 / RTL8366RB_PVCR_PORT_SHIFT)
-#define RTL8366RB_PVCR_PORT_MASK 0x000f
-#define RTL8366RB_PVCR_REG(_port) \
- (RTL8366RB_PVCR_BASE + _port / (RTL8366RB_PVCR_PORT_PERREG))
-#define RTL8366RB_PVCR_VAL(_port, _pvlan) \
- ((_pvlan & RTL8366RB_PVCR_PORT_MASK) << \
- ((_port % RTL8366RB_PVCR_PORT_PERREG) * RTL8366RB_PVCR_PORT_SHIFT))
-#define RTL8366RB_PVCR_GET(_port, _val) \
- (((_val) >> ((_port % RTL8366RB_PVCR_PORT_PERREG) * RTL8366RB_PVCR_PORT_SHIFT)) & RTL8366RB_PVCR_PORT_MASK)
+#define RTL8366_PVCR_BASE (sc->chip_type == 0 ? 0x0063 : 0x0058)
+#define RTL8366_PVCR_PORT_SHIFT 4
+#define RTL8366_PVCR_PORT_PERREG (16 / RTL8366_PVCR_PORT_SHIFT)
+#define RTL8366_PVCR_PORT_MASK 0x000f
+#define RTL8366_PVCR_REG(_port) \
+ (RTL8366_PVCR_BASE + _port / (RTL8366_PVCR_PORT_PERREG))
+#define RTL8366_PVCR_VAL(_port, _pvlan) \
+ ((_pvlan & RTL8366_PVCR_PORT_MASK) << \
+ ((_port % RTL8366_PVCR_PORT_PERREG) * RTL8366_PVCR_PORT_SHIFT))
+#define RTL8366_PVCR_GET(_port, _val) \
+ (((_val) >> ((_port % RTL8366_PVCR_PORT_PERREG) * RTL8366_PVCR_PORT_SHIFT)) & RTL8366_PVCR_PORT_MASK)
/* Reset Control */
-#define RTL8366RB_RCR 0x0100
-#define RTL8366RB_RCR_HARD_RESET 0x0001
-#define RTL8366RB_RCR_SOFT_RESET 0x0002
+#define RTL8366_RCR 0x0100
+#define RTL8366_RCR_HARD_RESET 0x0001
+#define RTL8366_RCR_SOFT_RESET 0x0002
/* Chip Version Control: CHIP_VER[3:0] */
-#define RTL8366RB_CVCR 0x050A
+#define RTL8366_CVCR (sc->chip_type == 0 ? 0x050A : 0x0104)
/* Chip Identifier */
#define RTL8366RB_CIR 0x0509
#define RTL8366RB_CIR_ID8366RB 0x5937
+#define RTL8366SR_CIR 0x0105
+#define RTL8366SR_CIR_ID8366SR 0x8366
/* VLAN Ingress Control 2: [5:0] */
-#define RTL8366RB_VIC2R 0x037f
+#define RTL8366_VIC2R 0x037f
/* MIB registers */
-#define RTL8366RB_MCNT_BASE 0x1000
-#define RTL8366RB_MCTLR 0x13f0
-#define RTL8366RB_MCTLR_BUSY 0x0001
-#define RTL8366RB_MCTLR_RESET 0x0002
-#define RTL8366RB_MCTLR_RESET_PORT_MASK 0x00fc
-#define RTL8366RB_MCTLR_RESET_ALL 0x0800
-
-#define RTL8366RB_MCNT(_port, _r) \
- (RTL8366RB_MCNT_BASE + 0x50 * (_port) + (_r))
-#define RTL8366RB_MCTLR_RESET_PORT(_p) \
+#define RTL8366_MCNT_BASE 0x1000
+#define RTL8366_MCTLR (sc->chip_type == 0 ? 0x13f0 : 0x11F0)
+#define RTL8366_MCTLR_BUSY 0x0001
+#define RTL8366_MCTLR_RESET 0x0002
+#define RTL8366_MCTLR_RESET_PORT_MASK 0x00fc
+#define RTL8366_MCTLR_RESET_ALL 0x0800
+
+#define RTL8366_MCNT(_port, _r) \
+ (RTL8366_MCNT_BASE + 0x50 * (_port) + (_r))
+#define RTL8366_MCTLR_RESET_PORT(_p) \
(1 << ((_p) + 2))
/* PHY Access Control */
-#define RTL8366RB_PACR 0x8000
-#define RTL8366RB_PACR_WRITE 0x0000
-#define RTL8366RB_PACR_READ 0x0001
+#define RTL8366_PACR (sc->chip_type == 0 ? 0x8000 : 0x8028)
+#define RTL8366_PACR_WRITE 0x0000
+#define RTL8366_PACR_READ 0x0001
/* PHY Access Data */
-#define RTL8366RB_PADR 0x8002
+#define RTL8366_PADR (sc->chip_type == 0 ? 0x8002 : 0x8029)
-#define RTL8366RB_PHYREG(phy, page, reg) \
- (RTL8366RB_PACR | (1 << (((phy) & 0x1f) + 9)) | (((page) & 0xf) << 5) | ((reg) & 0x1f))
+#define RTL8366_PHYREG(phy, page, reg) \
+ (0x8000 | (1 << (((phy) & 0x1f) + 9)) | (((page) & (sc->chip_type == 0 ? 0xf : 0x7)) << 5) | ((reg) & 0x1f))
/* general characteristics of the chip */
-#define RTL8366RB_CPU_PORT 5
-#define RTL8366RB_NUM_PORTS 6
-#define RTL8366RB_NUM_PHYS (RTL8366RB_NUM_PORTS-1)
-#define RTL8366RB_NUM_VLANS 16
-#define RTL8366RB_NUM_PHY_REG 32
+#define RTL8366_CPU_PORT 5
+#define RTL8366_NUM_PORTS 6
+#define RTL8366_NUM_PHYS (RTL8366_NUM_PORTS-1)
+#define RTL8366_NUM_VLANS 16
+#define RTL8366_NUM_PHY_REG 32
#endif
diff --git a/sys/dev/fdt/fdt_arm_platform.c b/sys/dev/fdt/fdt_arm_platform.c
index 22e935b146f3..fe1f40461689 100644
--- a/sys/dev/fdt/fdt_arm_platform.c
+++ b/sys/dev/fdt/fdt_arm_platform.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <arm/include/platformvar.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/fdt/fdt_common.h>
#include "platform_if.h"
@@ -58,7 +59,7 @@ fdt_platform_probe(platform_t plat)
/* Is the device is compatible? */
root = OF_finddevice("/");
compat = FDT_PLATFORM(plat)->fdt_compatible;
- if (fdt_is_compatible(root, compat) != 0)
+ if (ofw_bus_node_is_compatible(root, compat) != 0)
return 0;
/* Not compatible, return an error */
diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index 2f4555f81a4d..3e59fb977075 100644
--- a/sys/dev/fdt/fdt_common.c
+++ b/sys/dev/fdt/fdt_common.c
@@ -69,6 +69,8 @@ vm_offset_t fdt_immr_size;
struct fdt_ic_list fdt_ic_list_head = SLIST_HEAD_INITIALIZER(fdt_ic_list_head);
+static int fdt_is_compatible(phandle_t, const char *);
+
static int
fdt_get_range_by_busaddr(phandle_t node, u_long addr, u_long *base,
u_long *size)
@@ -242,7 +244,7 @@ moveon:
* Note the buffer has to be on the stack since malloc() is usually not
* available in such cases either.
*/
-int
+static int
fdt_is_compatible(phandle_t node, const char *compatstr)
{
char buf[FDT_COMPAT_LEN];
@@ -419,13 +421,13 @@ fdt_addrsize_cells(phandle_t node, int *addr_cells, int *size_cells)
* Retrieve #{address,size}-cells.
*/
cell_size = sizeof(cell);
- if (OF_getprop(node, "#address-cells", &cell, cell_size) < cell_size)
- cell = 2;
- *addr_cells = fdt32_to_cpu((int)cell);
+ if (OF_getencprop(node, "#address-cells", &cell, cell_size) < cell_size)
+ *addr_cells = 2;
+ *addr_cells = (int)cell;
- if (OF_getprop(node, "#size-cells", &cell, cell_size) < cell_size)
+ if (OF_getencprop(node, "#size-cells", &cell, cell_size) < cell_size)
cell = 1;
- *size_cells = fdt32_to_cpu((int)cell);
+ *size_cells = (int)cell;
if (*addr_cells > 3 || *size_cells > 2)
return (ERANGE);
@@ -540,11 +542,11 @@ fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc)
phy_node = OF_node_from_xref(phy_handle);
- if (OF_getprop(phy_node, "reg", (void *)&phy_reg,
+ if (OF_getencprop(phy_node, "reg", (void *)&phy_reg,
sizeof(phy_reg)) <= 0)
return (ENXIO);
- *phy_addr = fdt32_to_cpu(phy_reg);
+ *phy_addr = phy_reg;
/*
* Search for softc used to communicate with phy.
diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h
index afddc310c127..81ce4bfae2ea 100644
--- a/sys/dev/fdt/fdt_common.h
+++ b/sys/dev/fdt/fdt_common.h
@@ -94,7 +94,6 @@ int fdt_get_phyaddr(phandle_t, device_t, int *, void **);
int fdt_get_range(phandle_t, int, u_long *, u_long *);
int fdt_immr_addr(vm_offset_t);
int fdt_regsize(phandle_t, u_long *, u_long *);
-int fdt_is_compatible(phandle_t, const char *);
int fdt_is_compatible_strict(phandle_t, const char *);
int fdt_is_enabled(phandle_t);
int fdt_pm_is_enabled(phandle_t);
diff --git a/sys/dev/fdt/fdt_powerpc.c b/sys/dev/fdt/fdt_powerpc.c
index 80cfa4b3a93a..3c3dccef0f32 100644
--- a/sys/dev/fdt/fdt_powerpc.c
+++ b/sys/dev/fdt/fdt_powerpc.c
@@ -112,7 +112,7 @@ fdt_fixup_fman(phandle_t root)
* That frequency is equal to /soc node bus-frequency.
*/
for (node = OF_child(node); node != 0; node = OF_peer(node)) {
- if (fdt_is_compatible(node, "fsl,fman") == 0)
+ if (ofw_bus_node_is_compatible(node, "fsl,fman") == 0)
continue;
if (OF_setprop(node, "clock-frequency", (void *)&freq,
diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c
index 421af9d659de..056dd3193d4f 100644
--- a/sys/dev/gpio/gpiobus.c
+++ b/sys/dev/gpio/gpiobus.c
@@ -855,5 +855,6 @@ driver_t gpiobus_driver = {
devclass_t gpiobus_devclass;
-DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0);
+EARLY_DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
MODULE_VERSION(gpiobus, 1);
diff --git a/sys/dev/gpio/gpiopower.c b/sys/dev/gpio/gpiopower.c
new file mode 100644
index 000000000000..98b635e3fd2a
--- /dev/null
+++ b/sys/dev/gpio/gpiopower.c
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2016 Justin Hibbits
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/eventhandler.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/reboot.h>
+
+#include <dev/ofw/ofw_bus.h>
+
+#include <dev/gpio/gpiobusvar.h>
+
+struct gpiopower_softc {
+ gpio_pin_t sc_pin;
+ int sc_rbmask;
+};
+
+static void gpiopower_assert(device_t dev, int howto);
+
+static int
+gpiopower_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "gpio-poweroff")) {
+ device_set_desc(dev, "GPIO poweroff control");
+ return (0);
+ } else if (ofw_bus_is_compatible(dev, "gpio-restart")) {
+ device_set_desc(dev, "GPIO restart control");
+ return (0);
+ }
+
+ return (ENXIO);
+}
+
+static int
+gpiopower_attach(device_t dev)
+{
+ struct gpiopower_softc *sc;
+ phandle_t node;
+
+ sc = device_get_softc(dev);
+
+ if ((node = ofw_bus_get_node(dev)) == -1)
+ return (ENXIO);
+
+ ofw_gpiobus_parse_gpios(dev, "gpios", &sc->sc_pin);
+ if (sc->sc_pin == NULL) {
+ device_printf(dev, "failed to map GPIO pin\n");
+ return (ENXIO);
+ }
+
+ if (ofw_bus_is_compatible(dev, "gpio-poweroff"))
+ sc->sc_rbmask = RB_HALT | RB_POWEROFF;
+ else
+ sc->sc_rbmask = 0;
+ EVENTHANDLER_REGISTER(shutdown_final, gpiopower_assert, dev,
+ SHUTDOWN_PRI_LAST);
+ gpio_pin_setflags(sc->sc_pin, GPIO_PIN_OUTPUT);
+
+ return (0);
+}
+
+static void
+gpiopower_assert(device_t dev, int howto)
+{
+ struct gpiopower_softc *sc;
+ int do_assert;
+
+ sc = device_get_softc(dev);
+ do_assert = sc->sc_rbmask ? (sc->sc_rbmask & howto) :
+ ((howto & RB_HALT) == 0);
+
+ if (!do_assert)
+ return;
+
+ if (howto & RB_POWEROFF)
+ device_printf(dev, "powering system off\n");
+ else if ((howto & RB_HALT) == 0)
+ device_printf(dev, "resetting system\n");
+ else
+ return;
+
+ gpio_pin_set_active(sc->sc_pin, true);
+
+ /* Wait a second for it to trip */
+ DELAY(10000000);
+}
+
+static devclass_t gpiopower_devclass;
+
+static device_method_t gpiopower_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, gpiopower_probe),
+ DEVMETHOD(device_attach, gpiopower_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t gpiopower_driver = {
+ "gpiopower",
+ gpiopower_methods,
+ sizeof(struct gpiopower_softc)
+};
+
+DRIVER_MODULE(gpiopower, simplebus, gpiopower_driver, gpiopower_devclass, 0, 0);
+MODULE_DEPEND(gpiopower, gpiobus, 1, 1, 1);
diff --git a/sys/dev/hyperv/pcib/vmbus_pcib.c b/sys/dev/hyperv/pcib/vmbus_pcib.c
new file mode 100644
index 000000000000..2fb2c0259d53
--- /dev/null
+++ b/sys/dev/hyperv/pcib/vmbus_pcib.c
@@ -0,0 +1,1791 @@
+/*-
+ * Copyright (c) 2016 Microsoft Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/lock.h>
+#include <sys/sx.h>
+#include <sys/smp.h>
+#include <sys/sysctl.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/mutex.h>
+#include <sys/errno.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+
+#include <machine/atomic.h>
+#include <machine/bus.h>
+#include <machine/frame.h>
+#include <machine/pci_cfgreg.h>
+#include <machine/resource.h>
+
+#include <sys/pciio.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pci_private.h>
+#include <dev/pci/pcib_private.h>
+#include "pcib_if.h"
+
+#include <machine/intr_machdep.h>
+#include <x86/apicreg.h>
+
+#include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/hyperv_busdma.h>
+#include <dev/hyperv/include/vmbus_xact.h>
+#include <dev/hyperv/vmbus/vmbus_reg.h>
+#include <dev/hyperv/vmbus/vmbus_chanvar.h>
+
+#include "vmbus_if.h"
+
+#if __FreeBSD_version < 1100000
+typedef u_long rman_res_t;
+#define RM_MAX_END (~(rman_res_t)0)
+#endif
+
+struct completion {
+ unsigned int done;
+ struct mtx lock;
+};
+
+static void
+init_completion(struct completion *c)
+{
+ memset(c, 0, sizeof(*c));
+ mtx_init(&c->lock, "hvcmpl", NULL, MTX_DEF);
+ c->done = 0;
+}
+
+static void
+free_completion(struct completion *c)
+{
+ mtx_destroy(&c->lock);
+}
+
+static void
+complete(struct completion *c)
+{
+ mtx_lock(&c->lock);
+ c->done++;
+ mtx_unlock(&c->lock);
+ wakeup(c);
+}
+
+static void
+wait_for_completion(struct completion *c)
+{
+ mtx_lock(&c->lock);
+ while (c->done == 0)
+ mtx_sleep(c, &c->lock, 0, "hvwfc", 0);
+ c->done--;
+ mtx_unlock(&c->lock);
+}
+
+#define PCI_MAKE_VERSION(major, minor) ((uint32_t)(((major) << 16) | (major)))
+
+enum {
+ PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1),
+ PCI_PROTOCOL_VERSION_CURRENT = PCI_PROTOCOL_VERSION_1_1
+};
+
+#define PCI_CONFIG_MMIO_LENGTH 0x2000
+#define CFG_PAGE_OFFSET 0x1000
+#define CFG_PAGE_SIZE (PCI_CONFIG_MMIO_LENGTH - CFG_PAGE_OFFSET)
+
+/*
+ * Message Types
+ */
+
+enum pci_message_type {
+ /*
+ * Version 1.1
+ */
+ PCI_MESSAGE_BASE = 0x42490000,
+ PCI_BUS_RELATIONS = PCI_MESSAGE_BASE + 0,
+ PCI_QUERY_BUS_RELATIONS = PCI_MESSAGE_BASE + 1,
+ PCI_POWER_STATE_CHANGE = PCI_MESSAGE_BASE + 4,
+ PCI_QUERY_RESOURCE_REQUIREMENTS = PCI_MESSAGE_BASE + 5,
+ PCI_QUERY_RESOURCE_RESOURCES = PCI_MESSAGE_BASE + 6,
+ PCI_BUS_D0ENTRY = PCI_MESSAGE_BASE + 7,
+ PCI_BUS_D0EXIT = PCI_MESSAGE_BASE + 8,
+ PCI_READ_BLOCK = PCI_MESSAGE_BASE + 9,
+ PCI_WRITE_BLOCK = PCI_MESSAGE_BASE + 0xA,
+ PCI_EJECT = PCI_MESSAGE_BASE + 0xB,
+ PCI_QUERY_STOP = PCI_MESSAGE_BASE + 0xC,
+ PCI_REENABLE = PCI_MESSAGE_BASE + 0xD,
+ PCI_QUERY_STOP_FAILED = PCI_MESSAGE_BASE + 0xE,
+ PCI_EJECTION_COMPLETE = PCI_MESSAGE_BASE + 0xF,
+ PCI_RESOURCES_ASSIGNED = PCI_MESSAGE_BASE + 0x10,
+ PCI_RESOURCES_RELEASED = PCI_MESSAGE_BASE + 0x11,
+ PCI_INVALIDATE_BLOCK = PCI_MESSAGE_BASE + 0x12,
+ PCI_QUERY_PROTOCOL_VERSION = PCI_MESSAGE_BASE + 0x13,
+ PCI_CREATE_INTERRUPT_MESSAGE = PCI_MESSAGE_BASE + 0x14,
+ PCI_DELETE_INTERRUPT_MESSAGE = PCI_MESSAGE_BASE + 0x15,
+ PCI_MESSAGE_MAXIMUM
+};
+
+/*
+ * Structures defining the virtual PCI Express protocol.
+ */
+
+union pci_version {
+ struct {
+ uint16_t minor_version;
+ uint16_t major_version;
+ } parts;
+ uint32_t version;
+} __packed;
+
+/*
+ * This representation is the one used in Windows, which is
+ * what is expected when sending this back and forth with
+ * the Hyper-V parent partition.
+ */
+union win_slot_encoding {
+ struct {
+ uint32_t slot:5;
+ uint32_t func:3;
+ uint32_t reserved:24;
+ } bits;
+ uint32_t val;
+} __packed;
+
+struct pci_func_desc {
+ uint16_t v_id; /* vendor ID */
+ uint16_t d_id; /* device ID */
+ uint8_t rev;
+ uint8_t prog_intf;
+ uint8_t subclass;
+ uint8_t base_class;
+ uint32_t subsystem_id;
+ union win_slot_encoding wslot;
+ uint32_t ser; /* serial number */
+} __packed;
+
+struct hv_msi_desc {
+ uint8_t vector;
+ uint8_t delivery_mode;
+ uint16_t vector_count;
+ uint32_t reserved;
+ uint64_t cpu_mask;
+} __packed;
+
+struct tran_int_desc {
+ uint16_t reserved;
+ uint16_t vector_count;
+ uint32_t data;
+ uint64_t address;
+} __packed;
+
+struct pci_message {
+ uint32_t type;
+} __packed;
+
+struct pci_child_message {
+ struct pci_message message_type;
+ union win_slot_encoding wslot;
+} __packed;
+
+struct pci_incoming_message {
+ struct vmbus_chanpkt_hdr hdr;
+ struct pci_message message_type;
+} __packed;
+
+struct pci_response {
+ struct vmbus_chanpkt_hdr hdr;
+ int32_t status; /* negative values are failures */
+} __packed;
+
+struct pci_packet {
+ void (*completion_func)(void *context, struct pci_response *resp,
+ int resp_packet_size);
+ void *compl_ctxt;
+
+ struct pci_message message[0];
+};
+
+/*
+ * Specific message types supporting the PCI protocol.
+ */
+
+struct pci_version_request {
+ struct pci_message message_type;
+ uint32_t protocol_version;
+ uint32_t is_last_attempt:1;
+ uint32_t reservedz:31;
+} __packed;
+
+struct pci_bus_d0_entry {
+ struct pci_message message_type;
+ uint32_t reserved;
+ uint64_t mmio_base;
+} __packed;
+
+struct pci_bus_relations {
+ struct pci_incoming_message incoming;
+ uint32_t device_count;
+ struct pci_func_desc func[0];
+} __packed;
+
+#define MAX_NUM_BARS (PCIR_MAX_BAR_0 + 1)
+struct pci_q_res_req_response {
+ struct vmbus_chanpkt_hdr hdr;
+ int32_t status; /* negative values are failures */
+ uint32_t probed_bar[MAX_NUM_BARS];
+} __packed;
+
+struct pci_resources_assigned {
+ struct pci_message message_type;
+ union win_slot_encoding wslot;
+ uint8_t memory_range[0x14][MAX_NUM_BARS]; /* unused here */
+ uint32_t msi_descriptors;
+ uint32_t reserved[4];
+} __packed;
+
+struct pci_create_interrupt {
+ struct pci_message message_type;
+ union win_slot_encoding wslot;
+ struct hv_msi_desc int_desc;
+} __packed;
+
+struct pci_create_int_response {
+ struct pci_response response;
+ uint32_t reserved;
+ struct tran_int_desc int_desc;
+} __packed;
+
+struct pci_delete_interrupt {
+ struct pci_message message_type;
+ union win_slot_encoding wslot;
+ struct tran_int_desc int_desc;
+} __packed;
+
+struct pci_dev_incoming {
+ struct pci_incoming_message incoming;
+ union win_slot_encoding wslot;
+} __packed;
+
+struct pci_eject_response {
+ struct pci_message message_type;
+ union win_slot_encoding wslot;
+ uint32_t status;
+} __packed;
+
+/*
+ * Driver specific state.
+ */
+
+enum hv_pcibus_state {
+ hv_pcibus_init = 0,
+ hv_pcibus_installed,
+};
+
+struct hv_pcibus {
+ device_t pcib;
+ device_t pci_bus;
+ struct vmbus_pcib_softc *sc;
+
+ uint16_t pci_domain;
+
+ enum hv_pcibus_state state;
+
+ struct resource *cfg_res;
+
+ struct completion query_completion, *query_comp;
+
+ struct mtx config_lock; /* Avoid two threads writing index page */
+ struct mtx device_list_lock; /* Protect lists below */
+ TAILQ_HEAD(, hv_pci_dev) children;
+ TAILQ_HEAD(, hv_dr_state) dr_list;
+
+ volatile int detaching;
+};
+
+struct hv_pci_dev {
+ TAILQ_ENTRY(hv_pci_dev) link;
+
+ struct pci_func_desc desc;
+
+ bool reported_missing;
+
+ struct hv_pcibus *hbus;
+ struct task eject_task;
+
+ TAILQ_HEAD(, hv_irq_desc) irq_desc_list;
+
+ /*
+ * What would be observed if one wrote 0xFFFFFFFF to a BAR and then
+ * read it back, for each of the BAR offsets within config space.
+ */
+ uint32_t probed_bar[MAX_NUM_BARS];
+};
+
+/*
+ * Tracks "Device Relations" messages from the host, which must be both
+ * processed in order.
+ */
+struct hv_dr_work {
+ struct task task;
+ struct hv_pcibus *bus;
+};
+
+struct hv_dr_state {
+ TAILQ_ENTRY(hv_dr_state) link;
+ uint32_t device_count;
+ struct pci_func_desc func[0];
+};
+
+struct hv_irq_desc {
+ TAILQ_ENTRY(hv_irq_desc) link;
+ struct tran_int_desc desc;
+ int irq;
+};
+
+#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+
+static uint32_t
+devfn_to_wslot(unsigned int devfn)
+{
+ union win_slot_encoding wslot;
+
+ wslot.val = 0;
+ wslot.bits.slot = PCI_SLOT(devfn);
+ wslot.bits.func = PCI_FUNC(devfn);
+
+ return (wslot.val);
+}
+
+static unsigned int
+wslot_to_devfn(uint32_t wslot)
+{
+ union win_slot_encoding encoding;
+ unsigned int slot;
+ unsigned int func;
+
+ encoding.val = wslot;
+
+ slot = encoding.bits.slot;
+ func = encoding.bits.func;
+
+ return (PCI_DEVFN(slot, func));
+}
+
+struct vmbus_pcib_softc {
+ struct vmbus_channel *chan;
+ void *rx_buf;
+
+ struct taskqueue *taskq;
+
+ struct hv_pcibus *hbus;
+};
+
+/* {44C4F61D-4444-4400-9D52-802E27EDE19F} */
+static const struct hyperv_guid g_pass_through_dev_type = {
+ .hv_guid = {0x1D, 0xF6, 0xC4, 0x44, 0x44, 0x44, 0x00, 0x44,
+ 0x9D, 0x52, 0x80, 0x2E, 0x27, 0xED, 0xE1, 0x9F}
+};
+
+struct hv_pci_compl {
+ struct completion host_event;
+ int32_t completion_status;
+};
+
+struct q_res_req_compl {
+ struct completion host_event;
+ struct hv_pci_dev *hpdev;
+};
+
+struct compose_comp_ctxt {
+ struct hv_pci_compl comp_pkt;
+ struct tran_int_desc int_desc;
+};
+
+static void
+hv_pci_generic_compl(void *context, struct pci_response *resp,
+ int resp_packet_size)
+{
+ struct hv_pci_compl *comp_pkt = context;
+
+ if (resp_packet_size >= sizeof(struct pci_response))
+ comp_pkt->completion_status = resp->status;
+ else
+ comp_pkt->completion_status = -1;
+
+ complete(&comp_pkt->host_event);
+}
+
+static void
+q_resource_requirements(void *context, struct pci_response *resp,
+ int resp_packet_size)
+{
+ struct q_res_req_compl *completion = context;
+ struct pci_q_res_req_response *q_res_req =
+ (struct pci_q_res_req_response *)resp;
+ int i;
+
+ if (resp->status < 0) {
+ printf("vmbus_pcib: failed to query resource requirements\n");
+ } else {
+ for (i = 0; i < MAX_NUM_BARS; i++)
+ completion->hpdev->probed_bar[i] =
+ q_res_req->probed_bar[i];
+ }
+
+ complete(&completion->host_event);
+}
+
+static void
+hv_pci_compose_compl(void *context, struct pci_response *resp,
+ int resp_packet_size)
+{
+ struct compose_comp_ctxt *comp_pkt = context;
+ struct pci_create_int_response *int_resp =
+ (struct pci_create_int_response *)resp;
+
+ comp_pkt->comp_pkt.completion_status = resp->status;
+ comp_pkt->int_desc = int_resp->int_desc;
+ complete(&comp_pkt->comp_pkt.host_event);
+}
+
+static void
+hv_int_desc_free(struct hv_pci_dev *hpdev, struct hv_irq_desc *hid)
+{
+ struct pci_delete_interrupt *int_pkt;
+ struct {
+ struct pci_packet pkt;
+ uint8_t buffer[sizeof(struct pci_delete_interrupt)];
+ } ctxt;
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message;
+ int_pkt->message_type.type = PCI_DELETE_INTERRUPT_MESSAGE;
+ int_pkt->wslot.val = hpdev->desc.wslot.val;
+ int_pkt->int_desc = hid->desc;
+
+ vmbus_chan_send(hpdev->hbus->sc->chan, VMBUS_CHANPKT_TYPE_INBAND, 0,
+ int_pkt, sizeof(*int_pkt), 0);
+
+ free(hid, M_DEVBUF);
+}
+
+static void
+hv_pci_delete_device(struct hv_pci_dev *hpdev)
+{
+ struct hv_pcibus *hbus = hpdev->hbus;
+ struct hv_irq_desc *hid, *tmp_hid;
+ device_t pci_dev;
+ int devfn;
+
+ devfn = wslot_to_devfn(hpdev->desc.wslot.val);
+
+ mtx_lock(&Giant);
+
+ pci_dev = pci_find_dbsf(hbus->pci_domain,
+ 0, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ if (pci_dev)
+ device_delete_child(hbus->pci_bus, pci_dev);
+
+ mtx_unlock(&Giant);
+
+ mtx_lock(&hbus->device_list_lock);
+ TAILQ_REMOVE(&hbus->children, hpdev, link);
+ mtx_unlock(&hbus->device_list_lock);
+
+ TAILQ_FOREACH_SAFE(hid, &hpdev->irq_desc_list, link, tmp_hid)
+ hv_int_desc_free(hpdev, hid);
+
+ free(hpdev, M_DEVBUF);
+}
+
+static struct hv_pci_dev *
+new_pcichild_device(struct hv_pcibus *hbus, struct pci_func_desc *desc)
+{
+ struct hv_pci_dev *hpdev;
+ struct pci_child_message *res_req;
+ struct q_res_req_compl comp_pkt;
+ struct {
+ struct pci_packet pkt;
+ uint8_t buffer[sizeof(struct pci_child_message)];
+ } ctxt;
+ int ret;
+
+ hpdev = malloc(sizeof(*hpdev), M_DEVBUF, M_WAITOK | M_ZERO);
+ hpdev->hbus = hbus;
+
+ TAILQ_INIT(&hpdev->irq_desc_list);
+
+ init_completion(&comp_pkt.host_event);
+ comp_pkt.hpdev = hpdev;
+
+ ctxt.pkt.compl_ctxt = &comp_pkt;
+ ctxt.pkt.completion_func = q_resource_requirements;
+
+ res_req = (struct pci_child_message *)&ctxt.pkt.message;
+ res_req->message_type.type = PCI_QUERY_RESOURCE_REQUIREMENTS;
+ res_req->wslot.val = desc->wslot.val;
+
+ ret = vmbus_chan_send(hbus->sc->chan,
+ VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
+ res_req, sizeof(*res_req), (uint64_t)&ctxt.pkt);
+ if (ret)
+ goto err;
+
+ wait_for_completion(&comp_pkt.host_event);
+ free_completion(&comp_pkt.host_event);
+
+ hpdev->desc = *desc;
+
+ mtx_lock(&hbus->device_list_lock);
+ TAILQ_INSERT_TAIL(&hbus->children, hpdev, link);
+ mtx_unlock(&hbus->device_list_lock);
+ return (hpdev);
+err:
+ free_completion(&comp_pkt.host_event);
+ free(hpdev, M_DEVBUF);
+ return (NULL);
+}
+
+#if __FreeBSD_version < 1100000
+
+/* Old versions don't have BUS_RESCAN(). Let's copy it from FreeBSD 11. */
+
+static struct pci_devinfo *
+pci_identify_function(device_t pcib, device_t dev, int domain, int busno,
+ int slot, int func, size_t dinfo_size)
+{
+ struct pci_devinfo *dinfo;
+
+ dinfo = pci_read_device(pcib, domain, busno, slot, func, dinfo_size);
+ if (dinfo != NULL)
+ pci_add_child(dev, dinfo);
+
+ return (dinfo);
+}
+
+static int
+pci_rescan(device_t dev)
+{
+#define REG(n, w) PCIB_READ_CONFIG(pcib, busno, s, f, n, w)
+ device_t pcib = device_get_parent(dev);
+ struct pci_softc *sc;
+ device_t child, *devlist, *unchanged;
+ int devcount, error, i, j, maxslots, oldcount;
+ int busno, domain, s, f, pcifunchigh;
+ uint8_t hdrtype;
+
+ /* No need to check for ARI on a rescan. */
+ error = device_get_children(dev, &devlist, &devcount);
+ if (error)
+ return (error);
+ if (devcount != 0) {
+ unchanged = malloc(devcount * sizeof(device_t), M_TEMP,
+ M_NOWAIT | M_ZERO);
+ if (unchanged == NULL) {
+ free(devlist, M_TEMP);
+ return (ENOMEM);
+ }
+ } else
+ unchanged = NULL;
+
+ sc = device_get_softc(dev);
+ domain = pcib_get_domain(dev);
+ busno = pcib_get_bus(dev);
+ maxslots = PCIB_MAXSLOTS(pcib);
+ for (s = 0; s <= maxslots; s++) {
+ /* If function 0 is not present, skip to the next slot. */
+ f = 0;
+ if (REG(PCIR_VENDOR, 2) == 0xffff)
+ continue;
+ pcifunchigh = 0;
+ hdrtype = REG(PCIR_HDRTYPE, 1);
+ if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
+ continue;
+ if (hdrtype & PCIM_MFDEV)
+ pcifunchigh = PCIB_MAXFUNCS(pcib);
+ for (f = 0; f <= pcifunchigh; f++) {
+ if (REG(PCIR_VENDOR, 2) == 0xffff)
+ continue;
+
+ /*
+ * Found a valid function. Check if a
+ * device_t for this device already exists.
+ */
+ for (i = 0; i < devcount; i++) {
+ child = devlist[i];
+ if (child == NULL)
+ continue;
+ if (pci_get_slot(child) == s &&
+ pci_get_function(child) == f) {
+ unchanged[i] = child;
+ goto next_func;
+ }
+ }
+
+ pci_identify_function(pcib, dev, domain, busno, s, f,
+ sizeof(struct pci_devinfo));
+ next_func:;
+ }
+ }
+
+ /* Remove devices that are no longer present. */
+ for (i = 0; i < devcount; i++) {
+ if (unchanged[i] != NULL)
+ continue;
+ device_delete_child(dev, devlist[i]);
+ }
+
+ free(devlist, M_TEMP);
+ oldcount = devcount;
+
+ /* Try to attach the devices just added. */
+ error = device_get_children(dev, &devlist, &devcount);
+ if (error) {
+ free(unchanged, M_TEMP);
+ return (error);
+ }
+
+ for (i = 0; i < devcount; i++) {
+ for (j = 0; j < oldcount; j++) {
+ if (devlist[i] == unchanged[j])
+ goto next_device;
+ }
+
+ device_probe_and_attach(devlist[i]);
+ next_device:;
+ }
+
+ free(unchanged, M_TEMP);
+ free(devlist, M_TEMP);
+ return (0);
+#undef REG
+}
+
+#else
+
+static int
+pci_rescan(device_t dev)
+{
+ return (BUS_RESCAN(dev));
+}
+
+#endif
+
+static void
+pci_devices_present_work(void *arg, int pending __unused)
+{
+ struct hv_dr_work *dr_wrk = arg;
+ struct hv_dr_state *dr = NULL;
+ struct hv_pcibus *hbus;
+ uint32_t child_no;
+ bool found;
+ struct pci_func_desc *new_desc;
+ struct hv_pci_dev *hpdev, *tmp_hpdev;
+ struct completion *query_comp;
+ bool need_rescan = false;
+
+ hbus = dr_wrk->bus;
+ free(dr_wrk, M_DEVBUF);
+
+ /* Pull this off the queue and process it if it was the last one. */
+ mtx_lock(&hbus->device_list_lock);
+ while (!TAILQ_EMPTY(&hbus->dr_list)) {
+ dr = TAILQ_FIRST(&hbus->dr_list);
+ TAILQ_REMOVE(&hbus->dr_list, dr, link);
+
+ /* Throw this away if the list still has stuff in it. */
+ if (!TAILQ_EMPTY(&hbus->dr_list)) {
+ free(dr, M_DEVBUF);
+ continue;
+ }
+ }
+ mtx_unlock(&hbus->device_list_lock);
+
+ if (!dr)
+ return;
+
+ /* First, mark all existing children as reported missing. */
+ mtx_lock(&hbus->device_list_lock);
+ TAILQ_FOREACH(hpdev, &hbus->children, link)
+ hpdev->reported_missing = true;
+ mtx_unlock(&hbus->device_list_lock);
+
+ /* Next, add back any reported devices. */
+ for (child_no = 0; child_no < dr->device_count; child_no++) {
+ found = false;
+ new_desc = &dr->func[child_no];
+
+ mtx_lock(&hbus->device_list_lock);
+ TAILQ_FOREACH(hpdev, &hbus->children, link) {
+ if ((hpdev->desc.wslot.val ==
+ new_desc->wslot.val) &&
+ (hpdev->desc.v_id == new_desc->v_id) &&
+ (hpdev->desc.d_id == new_desc->d_id) &&
+ (hpdev->desc.ser == new_desc->ser)) {
+ hpdev->reported_missing = false;
+ found = true;
+ break;
+ }
+ }
+ mtx_unlock(&hbus->device_list_lock);
+
+ if (!found) {
+ if (!need_rescan)
+ need_rescan = true;
+
+ hpdev = new_pcichild_device(hbus, new_desc);
+ if (!hpdev)
+ printf("vmbus_pcib: failed to add a child\n");
+ }
+ }
+
+ /* Remove missing device(s), if any */
+ TAILQ_FOREACH_SAFE(hpdev, &hbus->children, link, tmp_hpdev) {
+ if (hpdev->reported_missing)
+ hv_pci_delete_device(hpdev);
+ }
+
+ /* Rescan the bus to find any new device, if necessary. */
+ if (hbus->state == hv_pcibus_installed && need_rescan)
+ pci_rescan(hbus->pci_bus);
+
+ /* Wake up hv_pci_query_relations(), if it's waiting. */
+ query_comp = hbus->query_comp;
+ if (query_comp) {
+ hbus->query_comp = NULL;
+ complete(query_comp);
+ }
+
+ free(dr, M_DEVBUF);
+}
+
+static struct hv_pci_dev *
+get_pcichild_wslot(struct hv_pcibus *hbus, uint32_t wslot)
+{
+ struct hv_pci_dev *hpdev, *ret = NULL;
+
+ mtx_lock(&hbus->device_list_lock);
+ TAILQ_FOREACH(hpdev, &hbus->children, link) {
+ if (hpdev->desc.wslot.val == wslot) {
+ ret = hpdev;
+ break;
+ }
+ }
+ mtx_unlock(&hbus->device_list_lock);
+
+ return (ret);
+}
+
+static void
+hv_pci_devices_present(struct hv_pcibus *hbus,
+ struct pci_bus_relations *relations)
+{
+ struct hv_dr_state *dr;
+ struct hv_dr_work *dr_wrk;
+ unsigned long dr_size;
+
+ if (hbus->detaching && relations->device_count > 0)
+ return;
+
+ dr_size = offsetof(struct hv_dr_state, func) +
+ (sizeof(struct pci_func_desc) * relations->device_count);
+ dr = malloc(dr_size, M_DEVBUF, M_WAITOK | M_ZERO);
+
+ dr->device_count = relations->device_count;
+ if (dr->device_count != 0)
+ memcpy(dr->func, relations->func,
+ sizeof(struct pci_func_desc) * dr->device_count);
+
+ mtx_lock(&hbus->device_list_lock);
+ TAILQ_INSERT_TAIL(&hbus->dr_list, dr, link);
+ mtx_unlock(&hbus->device_list_lock);
+
+ dr_wrk = malloc(sizeof(*dr_wrk), M_DEVBUF, M_WAITOK | M_ZERO);
+ dr_wrk->bus = hbus;
+ TASK_INIT(&dr_wrk->task, 0, pci_devices_present_work, dr_wrk);
+ taskqueue_enqueue(hbus->sc->taskq, &dr_wrk->task);
+}
+
+static void
+hv_eject_device_work(void *arg, int pending __unused)
+{
+ struct hv_pci_dev *hpdev = arg;
+ union win_slot_encoding wslot = hpdev->desc.wslot;
+ struct hv_pcibus *hbus = hpdev->hbus;
+ struct pci_eject_response *eject_pkt;
+ struct {
+ struct pci_packet pkt;
+ uint8_t buffer[sizeof(struct pci_eject_response)];
+ } ctxt;
+
+ hv_pci_delete_device(hpdev);
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ eject_pkt = (struct pci_eject_response *)&ctxt.pkt.message;
+ eject_pkt->message_type.type = PCI_EJECTION_COMPLETE;
+ eject_pkt->wslot.val = wslot.val;
+ vmbus_chan_send(hbus->sc->chan, VMBUS_CHANPKT_TYPE_INBAND, 0,
+ eject_pkt, sizeof(*eject_pkt), 0);
+}
+
+static void
+hv_pci_eject_device(struct hv_pci_dev *hpdev)
+{
+ struct hv_pcibus *hbus = hpdev->hbus;
+ struct taskqueue *taskq;
+
+ if (hbus->detaching)
+ return;
+
+ /*
+ * Push this task into the same taskqueue on which
+ * vmbus_pcib_attach() runs, so we're sure this task can't run
+ * concurrently with vmbus_pcib_attach().
+ */
+ TASK_INIT(&hpdev->eject_task, 0, hv_eject_device_work, hpdev);
+ taskq = vmbus_chan_mgmt_tq(hbus->sc->chan);
+ taskqueue_enqueue(taskq, &hpdev->eject_task);
+}
+
+#define PCIB_PACKET_SIZE 0x100
+
+static void
+vmbus_pcib_on_channel_callback(struct vmbus_channel *chan, void *arg)
+{
+ struct vmbus_pcib_softc *sc = arg;
+ struct hv_pcibus *hbus = sc->hbus;
+
+ void *buffer;
+ int bufferlen = PCIB_PACKET_SIZE;
+
+ struct pci_packet *comp_packet;
+ struct pci_response *response;
+ struct pci_incoming_message *new_msg;
+ struct pci_bus_relations *bus_rel;
+ struct pci_dev_incoming *dev_msg;
+ struct hv_pci_dev *hpdev;
+
+ buffer = sc->rx_buf;
+ do {
+ struct vmbus_chanpkt_hdr *pkt = buffer;
+ uint32_t bytes_rxed;
+ int ret;
+
+ bytes_rxed = bufferlen;
+ ret = vmbus_chan_recv_pkt(chan, pkt, &bytes_rxed);
+
+ if (ret == ENOBUFS) {
+ /* Handle large packet */
+ if (bufferlen > PCIB_PACKET_SIZE) {
+ free(buffer, M_DEVBUF);
+ buffer = NULL;
+ }
+
+ /* alloc new buffer */
+ buffer = malloc(bytes_rxed, M_DEVBUF, M_WAITOK | M_ZERO);
+ bufferlen = bytes_rxed;
+
+ continue;
+ }
+
+ if (ret != 0) {
+ /* ignore EIO or EAGAIN */
+ break;
+ }
+
+ if (bytes_rxed <= sizeof(struct pci_response))
+ continue;
+
+ switch (pkt->cph_type) {
+ case VMBUS_CHANPKT_TYPE_COMP:
+ comp_packet = (struct pci_packet *)pkt->cph_xactid;
+ response = (struct pci_response *)pkt;
+ comp_packet->completion_func(comp_packet->compl_ctxt,
+ response, bytes_rxed);
+ break;
+ case VMBUS_CHANPKT_TYPE_INBAND:
+ new_msg = (struct pci_incoming_message *)buffer;
+
+ switch (new_msg->message_type.type) {
+ case PCI_BUS_RELATIONS:
+ bus_rel = (struct pci_bus_relations *)buffer;
+
+ if (bus_rel->device_count == 0)
+ break;
+
+ if (bytes_rxed <
+ offsetof(struct pci_bus_relations, func) +
+ (sizeof(struct pci_func_desc) *
+ (bus_rel->device_count)))
+ break;
+
+ hv_pci_devices_present(hbus, bus_rel);
+ break;
+
+ case PCI_EJECT:
+ dev_msg = (struct pci_dev_incoming *)buffer;
+ hpdev = get_pcichild_wslot(hbus,
+ dev_msg->wslot.val);
+
+ if (hpdev)
+ hv_pci_eject_device(hpdev);
+
+ break;
+ default:
+ printf("vmbus_pcib: Unknown msg type 0x%x\n",
+ new_msg->message_type.type);
+ break;
+ }
+ break;
+ default:
+ printf("vmbus_pcib: Unknown VMBus msg type %hd\n",
+ pkt->cph_type);
+ break;
+ }
+ } while (1);
+
+ if (bufferlen > PCIB_PACKET_SIZE)
+ free(buffer, M_DEVBUF);
+}
+
+static int
+hv_pci_protocol_negotiation(struct hv_pcibus *hbus)
+{
+ struct pci_version_request *version_req;
+ struct hv_pci_compl comp_pkt;
+ struct {
+ struct pci_packet pkt;
+ uint8_t buffer[sizeof(struct pci_version_request)];
+ } ctxt;
+ int ret;
+
+ init_completion(&comp_pkt.host_event);
+
+ ctxt.pkt.completion_func = hv_pci_generic_compl;
+ ctxt.pkt.compl_ctxt = &comp_pkt;
+ version_req = (struct pci_version_request *)&ctxt.pkt.message;
+ version_req->message_type.type = PCI_QUERY_PROTOCOL_VERSION;
+ version_req->protocol_version = PCI_PROTOCOL_VERSION_CURRENT;
+ version_req->is_last_attempt = 1;
+
+ ret = vmbus_chan_send(hbus->sc->chan, VMBUS_CHANPKT_TYPE_INBAND,
+ VMBUS_CHANPKT_FLAG_RC, version_req, sizeof(*version_req),
+ (uint64_t)&ctxt.pkt);
+ if (ret)
+ goto out;
+
+ wait_for_completion(&comp_pkt.host_event);
+
+ if (comp_pkt.completion_status < 0) {
+ device_printf(hbus->pcib,
+ "vmbus_pcib version negotiation failed: %x\n",
+ comp_pkt.completion_status);
+ ret = EPROTO;
+ } else {
+ ret = 0;
+ }
+out:
+ free_completion(&comp_pkt.host_event);
+ return (ret);
+}
+
+/* Ask the host to send along the list of child devices */
+static int
+hv_pci_query_relations(struct hv_pcibus *hbus)
+{
+ struct pci_message message;
+ int ret;
+
+ message.type = PCI_QUERY_BUS_RELATIONS;
+ ret = vmbus_chan_send(hbus->sc->chan, VMBUS_CHANPKT_TYPE_INBAND, 0,
+ &message, sizeof(message), 0);
+ return (ret);
+}
+
+static int
+hv_pci_enter_d0(struct hv_pcibus *hbus)
+{
+ struct pci_bus_d0_entry *d0_entry;
+ struct hv_pci_compl comp_pkt;
+ struct {
+ struct pci_packet pkt;
+ uint8_t buffer[sizeof(struct pci_bus_d0_entry)];
+ } ctxt;
+ int ret;
+
+ /*
+ * Tell the host that the bus is ready to use, and moved into the
+ * powered-on state. This includes telling the host which region
+ * of memory-mapped I/O space has been chosen for configuration space
+ * access.
+ */
+ init_completion(&comp_pkt.host_event);
+
+ ctxt.pkt.completion_func = hv_pci_generic_compl;
+ ctxt.pkt.compl_ctxt = &comp_pkt;
+
+ d0_entry = (struct pci_bus_d0_entry *)&ctxt.pkt.message;
+ memset(d0_entry, 0, sizeof(*d0_entry));
+ d0_entry->message_type.type = PCI_BUS_D0ENTRY;
+ d0_entry->mmio_base = rman_get_start(hbus->cfg_res);
+
+ ret = vmbus_chan_send(hbus->sc->chan, VMBUS_CHANPKT_TYPE_INBAND,
+ VMBUS_CHANPKT_FLAG_RC, d0_entry, sizeof(*d0_entry),
+ (uint64_t)&ctxt.pkt);
+ if (ret)
+ goto out;
+
+ wait_for_completion(&comp_pkt.host_event);
+
+ if (comp_pkt.completion_status < 0) {
+ device_printf(hbus->pcib, "vmbus_pcib failed to enable D0\n");
+ ret = EPROTO;
+ } else {
+ ret = 0;
+ }
+
+out:
+ free_completion(&comp_pkt.host_event);
+ return (ret);
+}
+
+/*
+ * It looks this is only needed by Windows VM, but let's send the message too
+ * just to make the host happy.
+ */
+static int
+hv_send_resources_allocated(struct hv_pcibus *hbus)
+{
+ struct pci_resources_assigned *res_assigned;
+ struct hv_pci_compl comp_pkt;
+ struct hv_pci_dev *hpdev;
+ struct pci_packet *pkt;
+ uint32_t wslot;
+ int ret = 0;
+
+ pkt = malloc(sizeof(*pkt) + sizeof(*res_assigned),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+
+ for (wslot = 0; wslot < 256; wslot++) {
+ hpdev = get_pcichild_wslot(hbus, wslot);
+ if (!hpdev)
+ continue;
+
+ init_completion(&comp_pkt.host_event);
+
+ memset(pkt, 0, sizeof(*pkt) + sizeof(*res_assigned));
+ pkt->completion_func = hv_pci_generic_compl;
+ pkt->compl_ctxt = &comp_pkt;
+
+ res_assigned = (struct pci_resources_assigned *)&pkt->message;
+ res_assigned->message_type.type = PCI_RESOURCES_ASSIGNED;
+ res_assigned->wslot.val = hpdev->desc.wslot.val;
+
+ ret = vmbus_chan_send(hbus->sc->chan,
+ VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
+ &pkt->message, sizeof(*res_assigned), (uint64_t)pkt);
+ if (ret) {
+ free_completion(&comp_pkt.host_event);
+ break;
+ }
+
+ wait_for_completion(&comp_pkt.host_event);
+ free_completion(&comp_pkt.host_event);
+
+ if (comp_pkt.completion_status < 0) {
+ ret = EPROTO;
+ device_printf(hbus->pcib,
+ "failed to send PCI_RESOURCES_ASSIGNED\n");
+ break;
+ }
+ }
+
+ free(pkt, M_DEVBUF);
+ return (ret);
+}
+
+static int
+hv_send_resources_released(struct hv_pcibus *hbus)
+{
+ struct pci_child_message pkt;
+ struct hv_pci_dev *hpdev;
+ uint32_t wslot;
+ int ret;
+
+ for (wslot = 0; wslot < 256; wslot++) {
+ hpdev = get_pcichild_wslot(hbus, wslot);
+ if (!hpdev)
+ continue;
+
+ pkt.message_type.type = PCI_RESOURCES_RELEASED;
+ pkt.wslot.val = hpdev->desc.wslot.val;
+
+ ret = vmbus_chan_send(hbus->sc->chan,
+ VMBUS_CHANPKT_TYPE_INBAND, 0, &pkt, sizeof(pkt), 0);
+ if (ret)
+ return (ret);
+ }
+
+ return (0);
+}
+
+#define hv_cfg_read(x, s) \
+static inline uint##x##_t hv_cfg_read_##s(struct hv_pcibus *bus, \
+ bus_size_t offset) \
+{ \
+ return (bus_read_##s(bus->cfg_res, offset)); \
+}
+
+#define hv_cfg_write(x, s) \
+static inline void hv_cfg_write_##s(struct hv_pcibus *bus, \
+ bus_size_t offset, uint##x##_t val) \
+{ \
+ return (bus_write_##s(bus->cfg_res, offset, val)); \
+}
+
+hv_cfg_read(8, 1)
+hv_cfg_read(16, 2)
+hv_cfg_read(32, 4)
+
+hv_cfg_write(8, 1)
+hv_cfg_write(16, 2)
+hv_cfg_write(32, 4)
+
+static void
+_hv_pcifront_read_config(struct hv_pci_dev *hpdev, int where, int size,
+ uint32_t *val)
+{
+ struct hv_pcibus *hbus = hpdev->hbus;
+ bus_size_t addr = CFG_PAGE_OFFSET + where;
+
+ /*
+ * If the attempt is to read the IDs or the ROM BAR, simulate that.
+ */
+ if (where + size <= PCIR_COMMAND) {
+ memcpy(val, ((uint8_t *)&hpdev->desc.v_id) + where, size);
+ } else if (where >= PCIR_REVID && where + size <=
+ PCIR_CACHELNSZ) {
+ memcpy(val, ((uint8_t *)&hpdev->desc.rev) + where -
+ PCIR_REVID, size);
+ } else if (where >= PCIR_SUBVEND_0 && where + size <=
+ PCIR_BIOS) {
+ memcpy(val, (uint8_t *)&hpdev->desc.subsystem_id + where -
+ PCIR_SUBVEND_0, size);
+ } else if (where >= PCIR_BIOS && where + size <=
+ PCIR_CAP_PTR) {
+ /* ROM BARs are unimplemented */
+ *val = 0;
+ } else if ((where >= PCIR_INTLINE && where + size <=
+ PCIR_INTPIN) ||(where == PCIR_INTPIN && size == 1)) {
+ /*
+ * Interrupt Line and Interrupt PIN are hard-wired to zero
+ * because this front-end only supports message-signaled
+ * interrupts.
+ */
+ *val = 0;
+ } else if (where + size <= CFG_PAGE_SIZE) {
+ mtx_lock(&hbus->config_lock);
+
+ /* Choose the function to be read. */
+ hv_cfg_write_4(hbus, 0, hpdev->desc.wslot.val);
+
+ /* Make sure the function was chosen before we start reading.*/
+ mb();
+
+ /* Read from that function's config space. */
+ switch (size) {
+ case 1:
+ *((uint8_t *)val) = hv_cfg_read_1(hbus, addr);
+ break;
+ case 2:
+ *((uint16_t *)val) = hv_cfg_read_2(hbus, addr);
+ break;
+ default:
+ *((uint32_t *)val) = hv_cfg_read_4(hbus, addr);
+ break;
+ }
+ /*
+ * Make sure the write was done before we release the lock,
+ * allowing consecutive reads/writes.
+ */
+ mb();
+
+ mtx_unlock(&hbus->config_lock);
+ } else {
+ /* Invalid config read: it's unlikely to reach here. */
+ memset(val, 0, size);
+ }
+}
+
+static void
+_hv_pcifront_write_config(struct hv_pci_dev *hpdev, int where, int size,
+ uint32_t val)
+{
+ struct hv_pcibus *hbus = hpdev->hbus;
+ bus_size_t addr = CFG_PAGE_OFFSET + where;
+
+ /* SSIDs and ROM BARs are read-only */
+ if (where >= PCIR_SUBVEND_0 && where + size <= PCIR_CAP_PTR)
+ return;
+
+ if (where >= PCIR_COMMAND && where + size <= CFG_PAGE_SIZE) {
+ mtx_lock(&hbus->config_lock);
+
+ /* Choose the function to be written. */
+ hv_cfg_write_4(hbus, 0, hpdev->desc.wslot.val);
+
+ /* Make sure the function was chosen before we start writing.*/
+ wmb();
+
+ /* Write to that function's config space. */
+ switch (size) {
+ case 1:
+ hv_cfg_write_1(hbus, addr, (uint8_t)val);
+ break;
+ case 2:
+ hv_cfg_write_2(hbus, addr, (uint16_t)val);
+ break;
+ default:
+ hv_cfg_write_4(hbus, addr, (uint32_t)val);
+ break;
+ }
+
+ /*
+ * Make sure the write was done before we release the lock,
+ * allowing consecutive reads/writes.
+ */
+ mb();
+
+ mtx_unlock(&hbus->config_lock);
+ } else {
+ /* Invalid config write: it's unlikely to reach here. */
+ return;
+ }
+}
+
+static void
+vmbus_pcib_set_detaching(void *arg, int pending __unused)
+{
+ struct hv_pcibus *hbus = arg;
+
+ atomic_set_int(&hbus->detaching, 1);
+}
+
+static void
+vmbus_pcib_pre_detach(struct hv_pcibus *hbus)
+{
+ struct task task;
+
+ TASK_INIT(&task, 0, vmbus_pcib_set_detaching, hbus);
+
+ /*
+ * Make sure the channel callback won't push any possible new
+ * PCI_BUS_RELATIONS and PCI_EJECT tasks to sc->taskq.
+ */
+ vmbus_chan_run_task(hbus->sc->chan, &task);
+
+ taskqueue_drain_all(hbus->sc->taskq);
+}
+
+
+/*
+ * Standard probe entry point.
+ *
+ */
+static int
+vmbus_pcib_probe(device_t dev)
+{
+ if (VMBUS_PROBE_GUID(device_get_parent(dev), dev,
+ &g_pass_through_dev_type) == 0) {
+ device_set_desc(dev, "Hyper-V PCI Express Pass Through");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+/*
+ * Standard attach entry point.
+ *
+ */
+static int
+vmbus_pcib_attach(device_t dev)
+{
+ const int pci_ring_size = (4 * PAGE_SIZE);
+ const struct hyperv_guid *inst_guid;
+ struct vmbus_channel *channel;
+ struct vmbus_pcib_softc *sc;
+ struct hv_pcibus *hbus;
+ int rid = 0;
+ int ret;
+
+ hbus = malloc(sizeof(*hbus), M_DEVBUF, M_WAITOK | M_ZERO);
+ hbus->pcib = dev;
+
+ channel = vmbus_get_channel(dev);
+ inst_guid = vmbus_chan_guid_inst(channel);
+ hbus->pci_domain = inst_guid->hv_guid[9] |
+ (inst_guid->hv_guid[8] << 8);
+
+ mtx_init(&hbus->config_lock, "hbcfg", NULL, MTX_DEF);
+ mtx_init(&hbus->device_list_lock, "hbdl", NULL, MTX_DEF);
+ TAILQ_INIT(&hbus->children);
+ TAILQ_INIT(&hbus->dr_list);
+
+ hbus->cfg_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+ 0, RM_MAX_END, PCI_CONFIG_MMIO_LENGTH,
+ RF_ACTIVE | rman_make_alignment_flags(PAGE_SIZE));
+
+ if (!hbus->cfg_res) {
+ device_printf(dev, "failed to get resource for cfg window\n");
+ ret = ENXIO;
+ goto free_bus;
+ }
+
+ sc = device_get_softc(dev);
+ sc->chan = channel;
+ sc->rx_buf = malloc(PCIB_PACKET_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->hbus = hbus;
+
+ /*
+ * The taskq is used to handle PCI_BUS_RELATIONS and PCI_EJECT
+ * messages. NB: we can't handle the messages in the channel callback
+ * directly, because the message handlers need to send new messages
+ * to the host and waits for the host's completion messages, which
+ * must also be handled by the channel callback.
+ */
+ sc->taskq = taskqueue_create("vmbus_pcib_tq", M_WAITOK,
+ taskqueue_thread_enqueue, &sc->taskq);
+ taskqueue_start_threads(&sc->taskq, 1, PI_NET, "vmbus_pcib_tq");
+
+ hbus->sc = sc;
+
+ init_completion(&hbus->query_completion);
+ hbus->query_comp = &hbus->query_completion;
+
+ ret = vmbus_chan_open(sc->chan, pci_ring_size, pci_ring_size,
+ NULL, 0, vmbus_pcib_on_channel_callback, sc);
+ if (ret)
+ goto free_res;
+
+ ret = hv_pci_protocol_negotiation(hbus);
+ if (ret)
+ goto vmbus_close;
+
+ ret = hv_pci_query_relations(hbus);
+ if (ret)
+ goto vmbus_close;
+ wait_for_completion(hbus->query_comp);
+
+ ret = hv_pci_enter_d0(hbus);
+ if (ret)
+ goto vmbus_close;
+
+ ret = hv_send_resources_allocated(hbus);
+ if (ret)
+ goto vmbus_close;
+
+ hbus->pci_bus = device_add_child(dev, "pci", -1);
+ if (!hbus->pci_bus) {
+ device_printf(dev, "failed to create pci bus\n");
+ ret = ENXIO;
+ goto vmbus_close;
+ }
+
+ bus_generic_attach(dev);
+
+ hbus->state = hv_pcibus_installed;
+
+ return (0);
+
+vmbus_close:
+ vmbus_pcib_pre_detach(hbus);
+ vmbus_chan_close(sc->chan);
+free_res:
+ taskqueue_free(sc->taskq);
+ free_completion(&hbus->query_completion);
+ free(sc->rx_buf, M_DEVBUF);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, hbus->cfg_res);
+free_bus:
+ mtx_destroy(&hbus->device_list_lock);
+ mtx_destroy(&hbus->config_lock);
+ free(hbus, M_DEVBUF);
+ return (ret);
+}
+
+/*
+ * Standard detach entry point
+ */
+static int
+vmbus_pcib_detach(device_t dev)
+{
+ struct vmbus_pcib_softc *sc = device_get_softc(dev);
+ struct hv_pcibus *hbus = sc->hbus;
+ struct pci_message teardown_packet;
+ struct pci_bus_relations relations;
+ int ret;
+
+ vmbus_pcib_pre_detach(hbus);
+
+ if (hbus->state == hv_pcibus_installed)
+ bus_generic_detach(dev);
+
+ /* Delete any children which might still exist. */
+ memset(&relations, 0, sizeof(relations));
+ hv_pci_devices_present(hbus, &relations);
+
+ ret = hv_send_resources_released(hbus);
+ if (ret)
+ device_printf(dev, "failed to send PCI_RESOURCES_RELEASED\n");
+
+ teardown_packet.type = PCI_BUS_D0EXIT;
+ ret = vmbus_chan_send(sc->chan, VMBUS_CHANPKT_TYPE_INBAND, 0,
+ &teardown_packet, sizeof(struct pci_message), 0);
+ if (ret)
+ device_printf(dev, "failed to send PCI_BUS_D0EXIT\n");
+
+ taskqueue_drain_all(hbus->sc->taskq);
+ vmbus_chan_close(sc->chan);
+ taskqueue_free(sc->taskq);
+
+ free_completion(&hbus->query_completion);
+ free(sc->rx_buf, M_DEVBUF);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, hbus->cfg_res);
+
+ mtx_destroy(&hbus->device_list_lock);
+ mtx_destroy(&hbus->config_lock);
+ free(hbus, M_DEVBUF);
+
+ return (0);
+}
+
+static int
+vmbus_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *val)
+{
+ struct vmbus_pcib_softc *sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *val = sc->hbus->pci_domain;
+ return (0);
+
+ case PCIB_IVAR_BUS:
+ /* There is only bus 0. */
+ *val = 0;
+ return (0);
+ }
+ return (ENOENT);
+}
+
+static int
+vmbus_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t val)
+{
+ return (ENOENT);
+}
+
+static struct resource *
+vmbus_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+ unsigned int bar_no;
+ struct hv_pci_dev *hpdev;
+ struct vmbus_pcib_softc *sc = device_get_softc(dev);
+ struct resource *res;
+ unsigned int devfn;
+
+ if (type == PCI_RES_BUS)
+ return (pci_domain_alloc_bus(sc->hbus->pci_domain, child, rid,
+ start, end, count, flags));
+
+ /* Devices with port I/O BAR are not supported. */
+ if (type == SYS_RES_IOPORT)
+ return (NULL);
+
+ if (type == SYS_RES_MEMORY) {
+ devfn = PCI_DEVFN(pci_get_slot(child),
+ pci_get_function(child));
+ hpdev = get_pcichild_wslot(sc->hbus, devfn_to_wslot(devfn));
+ if (!hpdev)
+ return (NULL);
+
+ bar_no = PCI_RID2BAR(*rid);
+ if (bar_no >= MAX_NUM_BARS)
+ return (NULL);
+
+ /* Make sure a 32-bit BAR gets a 32-bit address */
+ if (!(hpdev->probed_bar[bar_no] & PCIM_BAR_MEM_64))
+ end = ulmin(end, 0xFFFFFFFF);
+ }
+
+ res = bus_generic_alloc_resource(dev, child, type, rid,
+ start, end, count, flags);
+ /*
+ * If this is a request for a specific range, assume it is
+ * correct and pass it up to the parent.
+ */
+ if (res == NULL && start + count - 1 == end)
+ res = bus_generic_alloc_resource(dev, child, type, rid,
+ start, end, count, flags);
+ return (res);
+}
+
+static int
+vmbus_pcib_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ struct vmbus_pcib_softc *sc = device_get_softc(dev);
+
+ if (type == PCI_RES_BUS)
+ return (pci_domain_release_bus(sc->hbus->pci_domain, child,
+ rid, r));
+
+ if (type == SYS_RES_IOPORT)
+ return (EINVAL);
+
+ return (bus_generic_release_resource(dev, child, type, rid, r));
+}
+
+#if __FreeBSD_version >= 1100000
+static int
+vmbus_pcib_get_cpus(device_t pcib, device_t dev, enum cpu_sets op,
+ size_t setsize, cpuset_t *cpuset)
+{
+ return (bus_get_cpus(pcib, op, setsize, cpuset));
+}
+#endif
+
+static uint32_t
+vmbus_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, int bytes)
+{
+ struct vmbus_pcib_softc *sc = device_get_softc(dev);
+ struct hv_pci_dev *hpdev;
+ unsigned int devfn = PCI_DEVFN(slot, func);
+ uint32_t data = 0;
+
+ KASSERT(bus == 0, ("bus should be 0, but is %u", bus));
+
+ hpdev = get_pcichild_wslot(sc->hbus, devfn_to_wslot(devfn));
+ if (!hpdev)
+ return (~0);
+
+ _hv_pcifront_read_config(hpdev, reg, bytes, &data);
+
+ return (data);
+}
+
+static void
+vmbus_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, uint32_t data, int bytes)
+{
+ struct vmbus_pcib_softc *sc = device_get_softc(dev);
+ struct hv_pci_dev *hpdev;
+ unsigned int devfn = PCI_DEVFN(slot, func);
+
+ KASSERT(bus == 0, ("bus should be 0, but is %u", bus));
+
+ hpdev = get_pcichild_wslot(sc->hbus, devfn_to_wslot(devfn));
+ if (!hpdev)
+ return;
+
+ _hv_pcifront_write_config(hpdev, reg, bytes, data);
+}
+
+static int
+vmbus_pcib_route_intr(device_t pcib, device_t dev, int pin)
+{
+ /* We only support MSI/MSI-X and don't support INTx interrupt. */
+ return (PCI_INVALID_IRQ);
+}
+
+static int
+vmbus_pcib_alloc_msi(device_t pcib, device_t dev, int count,
+ int maxcount, int *irqs)
+{
+ return (PCIB_ALLOC_MSI(device_get_parent(pcib), dev, count, maxcount,
+ irqs));
+}
+
+static int
+vmbus_pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs)
+{
+ return (PCIB_RELEASE_MSI(device_get_parent(pcib), dev, count, irqs));
+}
+
+static int
+vmbus_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
+{
+ return (PCIB_ALLOC_MSIX(device_get_parent(pcib), dev, irq));
+}
+
+static int
+vmbus_pcib_release_msix(device_t pcib, device_t dev, int irq)
+{
+ return (PCIB_RELEASE_MSIX(device_get_parent(pcib), dev, irq));
+}
+
+#define MSI_INTEL_ADDR_DEST 0x000ff000
+#define MSI_INTEL_DATA_INTVEC IOART_INTVEC /* Interrupt vector. */
+#define MSI_INTEL_DATA_DELFIXED IOART_DELFIXED
+
+static int
+vmbus_pcib_map_msi(device_t pcib, device_t child, int irq,
+ uint64_t *addr, uint32_t *data)
+{
+ unsigned int devfn;
+ struct hv_pci_dev *hpdev;
+
+ uint64_t v_addr;
+ uint32_t v_data;
+ struct hv_irq_desc *hid, *tmp_hid;
+ unsigned int cpu, vcpu_id;
+ unsigned int vector;
+
+ struct vmbus_pcib_softc *sc = device_get_softc(pcib);
+ struct pci_create_interrupt *int_pkt;
+ struct compose_comp_ctxt comp;
+ struct {
+ struct pci_packet pkt;
+ uint8_t buffer[sizeof(struct pci_create_interrupt)];
+ } ctxt;
+
+ int ret;
+
+ devfn = PCI_DEVFN(pci_get_slot(child), pci_get_function(child));
+ hpdev = get_pcichild_wslot(sc->hbus, devfn_to_wslot(devfn));
+ if (!hpdev)
+ return (ENOENT);
+
+ ret = PCIB_MAP_MSI(device_get_parent(pcib), child, irq,
+ &v_addr, &v_data);
+ if (ret)
+ return (ret);
+
+ TAILQ_FOREACH_SAFE(hid, &hpdev->irq_desc_list, link, tmp_hid) {
+ if (hid->irq == irq) {
+ TAILQ_REMOVE(&hpdev->irq_desc_list, hid, link);
+ hv_int_desc_free(hpdev, hid);
+ break;
+ }
+ }
+
+ cpu = (v_addr & MSI_INTEL_ADDR_DEST) >> 12;
+ vcpu_id = VMBUS_GET_VCPU_ID(device_get_parent(pcib), pcib, cpu);
+ vector = v_data & MSI_INTEL_DATA_INTVEC;
+
+ init_completion(&comp.comp_pkt.host_event);
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ ctxt.pkt.completion_func = hv_pci_compose_compl;
+ ctxt.pkt.compl_ctxt = &comp;
+
+ int_pkt = (struct pci_create_interrupt *)&ctxt.pkt.message;
+ int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE;
+ int_pkt->wslot.val = hpdev->desc.wslot.val;
+ int_pkt->int_desc.vector = vector;
+ int_pkt->int_desc.vector_count = 1;
+ int_pkt->int_desc.delivery_mode = MSI_INTEL_DATA_DELFIXED;
+ int_pkt->int_desc.cpu_mask = 1ULL << vcpu_id;
+
+ ret = vmbus_chan_send(sc->chan, VMBUS_CHANPKT_TYPE_INBAND,
+ VMBUS_CHANPKT_FLAG_RC, int_pkt, sizeof(*int_pkt),
+ (uint64_t)&ctxt.pkt);
+ if (ret) {
+ free_completion(&comp.comp_pkt.host_event);
+ return (ret);
+ }
+
+ wait_for_completion(&comp.comp_pkt.host_event);
+ free_completion(&comp.comp_pkt.host_event);
+
+ if (comp.comp_pkt.completion_status < 0)
+ return (EPROTO);
+
+ *addr = comp.int_desc.address;
+ *data = comp.int_desc.data;
+
+ hid = malloc(sizeof(struct hv_irq_desc), M_DEVBUF, M_WAITOK | M_ZERO);
+ hid->irq = irq;
+ hid->desc = comp.int_desc;
+ TAILQ_INSERT_TAIL(&hpdev->irq_desc_list, hid, link);
+
+ return (0);
+}
+
+static device_method_t vmbus_pcib_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, vmbus_pcib_probe),
+ DEVMETHOD(device_attach, vmbus_pcib_attach),
+ DEVMETHOD(device_detach, vmbus_pcib_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, vmbus_pcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, vmbus_pcib_write_ivar),
+ DEVMETHOD(bus_alloc_resource, vmbus_pcib_alloc_resource),
+ DEVMETHOD(bus_release_resource, vmbus_pcib_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+#if __FreeBSD_version >= 1100000
+ DEVMETHOD(bus_get_cpus, vmbus_pcib_get_cpus),
+#endif
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, pcib_maxslots),
+ DEVMETHOD(pcib_read_config, vmbus_pcib_read_config),
+ DEVMETHOD(pcib_write_config, vmbus_pcib_write_config),
+ DEVMETHOD(pcib_route_interrupt, vmbus_pcib_route_intr),
+ DEVMETHOD(pcib_alloc_msi, vmbus_pcib_alloc_msi),
+ DEVMETHOD(pcib_release_msi, vmbus_pcib_release_msi),
+ DEVMETHOD(pcib_alloc_msix, vmbus_pcib_alloc_msix),
+ DEVMETHOD(pcib_release_msix, vmbus_pcib_release_msix),
+ DEVMETHOD(pcib_map_msi, vmbus_pcib_map_msi),
+
+ DEVMETHOD_END
+};
+
+static devclass_t pcib_devclass;
+
+DEFINE_CLASS_0(pcib, vmbus_pcib_driver, vmbus_pcib_methods,
+ sizeof(struct vmbus_pcib_softc));
+DRIVER_MODULE(vmbus_pcib, vmbus, vmbus_pcib_driver, pcib_devclass, 0, 0);
+MODULE_DEPEND(vmbus_pcib, vmbus, 1, 1, 1);
+MODULE_DEPEND(vmbus_pcib, pci, 1, 1, 1);
diff --git a/sys/dev/hyperv/utilities/hv_snapshot.c b/sys/dev/hyperv/utilities/hv_snapshot.c
new file mode 100644
index 000000000000..23162973f2c9
--- /dev/null
+++ b/sys/dev/hyperv/utilities/hv_snapshot.c
@@ -0,0 +1,1061 @@
+/*-
+ * Copyright (c) 2016 Microsoft Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/taskqueue.h>
+#include <sys/selinfo.h>
+#include <sys/sysctl.h>
+#include <sys/poll.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/kthread.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/un.h>
+#include <sys/endian.h>
+#include <sys/sema.h>
+#include <sys/signal.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+#include <sys/mutex.h>
+#include <sys/callout.h>
+
+#include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/utilities/hv_utilreg.h>
+#include <dev/hyperv/utilities/vmbus_icreg.h>
+
+#include "hv_util.h"
+#include "hv_snapshot.h"
+#include "vmbus_if.h"
+
+#define VSS_MAJOR 5
+#define VSS_MINOR 0
+#define VSS_MSGVER VMBUS_IC_VERSION(VSS_MAJOR, VSS_MINOR)
+
+#define VSS_FWVER_MAJOR 3
+#define VSS_FWVER VMBUS_IC_VERSION(VSS_FWVER_MAJOR, 0)
+
+#define TIMEOUT_LIMIT (15) // seconds
+enum hv_vss_op {
+ VSS_OP_CREATE = 0,
+ VSS_OP_DELETE,
+ VSS_OP_HOT_BACKUP,
+ VSS_OP_GET_DM_INFO,
+ VSS_OP_BU_COMPLETE,
+ /*
+ * Following operations are only supported with IC version >= 5.0
+ */
+ VSS_OP_FREEZE, /* Freeze the file systems in the VM */
+ VSS_OP_THAW, /* Unfreeze the file systems */
+ VSS_OP_AUTO_RECOVER,
+ VSS_OP_COUNT /* Number of operations, must be last */
+};
+
+/*
+ * Header for all VSS messages.
+ */
+struct hv_vss_hdr {
+ struct vmbus_icmsg_hdr ic_hdr;
+ uint8_t operation;
+ uint8_t reserved[7];
+} __packed;
+
+
+/*
+ * Flag values for the hv_vss_check_feature. Here supports only
+ * one value.
+ */
+#define VSS_HBU_NO_AUTO_RECOVERY 0x00000005
+
+struct hv_vss_check_feature {
+ uint32_t flags;
+} __packed;
+
+struct hv_vss_check_dm_info {
+ uint32_t flags;
+} __packed;
+
+struct hv_vss_msg {
+ union {
+ struct hv_vss_hdr vss_hdr;
+ } hdr;
+ union {
+ struct hv_vss_check_feature vss_cf;
+ struct hv_vss_check_dm_info dm_info;
+ } body;
+} __packed;
+
+struct hv_vss_req {
+ struct hv_vss_opt_msg opt_msg; /* used to communicate with daemon */
+ struct hv_vss_msg msg; /* used to communicate with host */
+} __packed;
+
+/* hv_vss debug control */
+static int hv_vss_log = 0;
+
+#define hv_vss_log_error(...) do { \
+ if (hv_vss_log > 0) \
+ log(LOG_ERR, "hv_vss: " __VA_ARGS__); \
+} while (0)
+
+#define hv_vss_log_info(...) do { \
+ if (hv_vss_log > 1) \
+ log(LOG_INFO, "hv_vss: " __VA_ARGS__); \
+} while (0)
+
+static const struct vmbus_ic_desc vmbus_vss_descs[] = {
+ {
+ .ic_guid = { .hv_guid = {
+ 0x29, 0x2e, 0xfa, 0x35, 0x23, 0xea, 0x36, 0x42,
+ 0x96, 0xae, 0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40} },
+ .ic_desc = "Hyper-V VSS"
+ },
+ VMBUS_IC_DESC_END
+};
+
+static const char * vss_opt_name[] = {"None", "VSSCheck", "Freeze", "Thaw"};
+
+/* character device prototypes */
+static d_open_t hv_vss_dev_open;
+static d_close_t hv_vss_dev_close;
+static d_poll_t hv_vss_dev_daemon_poll;
+static d_ioctl_t hv_vss_dev_daemon_ioctl;
+
+static d_open_t hv_appvss_dev_open;
+static d_close_t hv_appvss_dev_close;
+static d_poll_t hv_appvss_dev_poll;
+static d_ioctl_t hv_appvss_dev_ioctl;
+
+/* hv_vss character device structure */
+static struct cdevsw hv_vss_cdevsw =
+{
+ .d_version = D_VERSION,
+ .d_open = hv_vss_dev_open,
+ .d_close = hv_vss_dev_close,
+ .d_poll = hv_vss_dev_daemon_poll,
+ .d_ioctl = hv_vss_dev_daemon_ioctl,
+ .d_name = FS_VSS_DEV_NAME,
+};
+
+static struct cdevsw hv_appvss_cdevsw =
+{
+ .d_version = D_VERSION,
+ .d_open = hv_appvss_dev_open,
+ .d_close = hv_appvss_dev_close,
+ .d_poll = hv_appvss_dev_poll,
+ .d_ioctl = hv_appvss_dev_ioctl,
+ .d_name = APP_VSS_DEV_NAME,
+};
+
+struct hv_vss_sc;
+/*
+ * Global state to track cdev
+ */
+struct hv_vss_dev_sc {
+ /*
+ * msg was transferred from host to notify queue, and
+ * ack queue. Finally, it was recyled to free list.
+ */
+ STAILQ_HEAD(, hv_vss_req_internal) to_notify_queue;
+ STAILQ_HEAD(, hv_vss_req_internal) to_ack_queue;
+ struct hv_vss_sc *sc;
+ struct proc *proc_task;
+ struct selinfo hv_vss_selinfo;
+};
+/*
+ * Global state to track and synchronize the transaction requests from the host.
+ * The VSS allows user to register their function to do freeze/thaw for application.
+ * VSS kernel will notify both vss daemon and user application if it is registered.
+ * The implementation state transition is illustrated by:
+ * https://clovertrail.github.io/assets/vssdot.png
+ */
+typedef struct hv_vss_sc {
+ struct hv_util_sc util_sc;
+ device_t dev;
+
+ struct task task;
+
+ /*
+ * mutex is used to protect access of list/queue,
+ * callout in request is also used this mutex.
+ */
+ struct mtx pending_mutex;
+ /*
+ * req_free_list contains all free items
+ */
+ LIST_HEAD(, hv_vss_req_internal) req_free_list;
+
+ /* Indicates if daemon registered with driver */
+ boolean_t register_done;
+
+ boolean_t app_register_done;
+
+ /* cdev for file system freeze/thaw */
+ struct cdev *hv_vss_dev;
+ /* cdev for application freeze/thaw */
+ struct cdev *hv_appvss_dev;
+
+ /* sc for app */
+ struct hv_vss_dev_sc app_sc;
+ /* sc for deamon */
+ struct hv_vss_dev_sc daemon_sc;
+} hv_vss_sc;
+
+typedef struct hv_vss_req_internal {
+ LIST_ENTRY(hv_vss_req_internal) link;
+ STAILQ_ENTRY(hv_vss_req_internal) slink;
+ struct hv_vss_req vss_req;
+
+ /* Rcv buffer for communicating with the host*/
+ uint8_t *rcv_buf;
+ /* Length of host message */
+ uint32_t host_msg_len;
+ /* Host message id */
+ uint64_t host_msg_id;
+
+ hv_vss_sc *sc;
+
+ struct callout callout;
+} hv_vss_req_internal;
+
+#define SEARCH_REMOVE_REQ_LOCKED(reqp, queue, link, tmp, id) \
+ do { \
+ STAILQ_FOREACH_SAFE(reqp, queue, link, tmp) { \
+ if (reqp->vss_req.opt_msg.msgid == id) { \
+ STAILQ_REMOVE(queue, \
+ reqp, hv_vss_req_internal, link); \
+ break; \
+ } \
+ } \
+ } while (0)
+
+static bool
+hv_vss_is_daemon_killed_after_launch(hv_vss_sc *sc)
+{
+ return (!sc->register_done && sc->daemon_sc.proc_task);
+}
+
+/*
+ * Callback routine that gets called whenever there is a message from host
+ */
+static void
+hv_vss_callback(struct vmbus_channel *chan __unused, void *context)
+{
+ hv_vss_sc *sc = (hv_vss_sc*)context;
+ if (hv_vss_is_daemon_killed_after_launch(sc))
+ hv_vss_log_info("%s: daemon was killed!\n", __func__);
+ if (sc->register_done || sc->daemon_sc.proc_task) {
+ hv_vss_log_info("%s: Queuing work item\n", __func__);
+ if (hv_vss_is_daemon_killed_after_launch(sc))
+ hv_vss_log_info("%s: daemon was killed!\n", __func__);
+ taskqueue_enqueue(taskqueue_thread, &sc->task);
+ } else {
+ hv_vss_log_info("%s: daemon has never been registered\n", __func__);
+ }
+ hv_vss_log_info("%s: received msg from host\n", __func__);
+}
+/*
+ * Send the response back to the host.
+ */
+static void
+hv_vss_respond_host(uint8_t *rcv_buf, struct vmbus_channel *ch,
+ uint32_t recvlen, uint64_t requestid, uint32_t error)
+{
+ struct vmbus_icmsg_hdr *hv_icmsg_hdrp;
+
+ hv_icmsg_hdrp = (struct vmbus_icmsg_hdr *)rcv_buf;
+
+ hv_icmsg_hdrp->ic_status = error;
+ hv_icmsg_hdrp->ic_flags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE;
+
+ error = vmbus_chan_send(ch, VMBUS_CHANPKT_TYPE_INBAND, 0,
+ rcv_buf, recvlen, requestid);
+ if (error)
+ hv_vss_log_info("%s: hv_vss_respond_host: sendpacket error:%d\n",
+ __func__, error);
+}
+
+static void
+hv_vss_notify_host_result_locked(struct hv_vss_req_internal *reqp, uint32_t status)
+{
+ struct hv_vss_msg* msg = (struct hv_vss_msg *)reqp->rcv_buf;
+ hv_vss_sc *sc = reqp->sc;
+ if (reqp->vss_req.opt_msg.opt == HV_VSS_CHECK) {
+ msg->body.vss_cf.flags = VSS_HBU_NO_AUTO_RECOVERY;
+ }
+ hv_vss_log_info("%s, %s response %s to host\n", __func__,
+ vss_opt_name[reqp->vss_req.opt_msg.opt],
+ status == HV_S_OK ? "Success" : "Fail");
+ hv_vss_respond_host(reqp->rcv_buf, vmbus_get_channel(reqp->sc->dev),
+ reqp->host_msg_len, reqp->host_msg_id, status);
+ /* recycle the request */
+ LIST_INSERT_HEAD(&sc->req_free_list, reqp, link);
+}
+
+static void
+hv_vss_notify_host_result(struct hv_vss_req_internal *reqp, uint32_t status)
+{
+ mtx_lock(&reqp->sc->pending_mutex);
+ hv_vss_notify_host_result_locked(reqp, status);
+ mtx_unlock(&reqp->sc->pending_mutex);
+}
+
+static void
+hv_vss_cp_vssreq_to_user(struct hv_vss_req_internal *reqp,
+ struct hv_vss_opt_msg *userdata)
+{
+ struct hv_vss_req *hv_vss_dev_buf;
+ hv_vss_dev_buf = &reqp->vss_req;
+ hv_vss_dev_buf->opt_msg.opt = HV_VSS_NONE;
+ switch (reqp->vss_req.msg.hdr.vss_hdr.operation) {
+ case VSS_OP_FREEZE:
+ hv_vss_dev_buf->opt_msg.opt = HV_VSS_FREEZE;
+ break;
+ case VSS_OP_THAW:
+ hv_vss_dev_buf->opt_msg.opt = HV_VSS_THAW;
+ break;
+ case VSS_OP_HOT_BACKUP:
+ hv_vss_dev_buf->opt_msg.opt = HV_VSS_CHECK;
+ break;
+ }
+ *userdata = hv_vss_dev_buf->opt_msg;
+ hv_vss_log_info("%s, read data from user for "
+ "%s (%ju) \n", __func__, vss_opt_name[userdata->opt],
+ (uintmax_t)userdata->msgid);
+}
+
+/**
+ * Remove the request id from app notifiy or ack queue,
+ * and recyle the request by inserting it to free list.
+ *
+ * When app was notified but not yet sending ack, the request
+ * should locate in either notify queue or ack queue.
+ */
+static struct hv_vss_req_internal*
+hv_vss_drain_req_queue_locked(hv_vss_sc *sc, uint64_t req_id)
+{
+ struct hv_vss_req_internal *reqp, *tmp;
+ SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->daemon_sc.to_notify_queue,
+ slink, tmp, req_id);
+ if (reqp == NULL)
+ SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->daemon_sc.to_ack_queue,
+ slink, tmp, req_id);
+ if (reqp == NULL)
+ SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->app_sc.to_notify_queue,
+ slink, tmp, req_id);
+ if (reqp == NULL)
+ SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->app_sc.to_ack_queue, slink,
+ tmp, req_id);
+ return (reqp);
+}
+/**
+ * Actions for daemon who has been notified.
+ */
+static void
+hv_vss_notified(struct hv_vss_dev_sc *dev_sc, struct hv_vss_opt_msg *userdata)
+{
+ struct hv_vss_req_internal *reqp;
+ mtx_lock(&dev_sc->sc->pending_mutex);
+ if (!STAILQ_EMPTY(&dev_sc->to_notify_queue)) {
+ reqp = STAILQ_FIRST(&dev_sc->to_notify_queue);
+ hv_vss_cp_vssreq_to_user(reqp, userdata);
+ STAILQ_REMOVE_HEAD(&dev_sc->to_notify_queue, slink);
+ /* insert the msg to queue for write */
+ STAILQ_INSERT_TAIL(&dev_sc->to_ack_queue, reqp, slink);
+ userdata->status = VSS_SUCCESS;
+ } else {
+ /* Timeout occur, thus request was removed from queue. */
+ hv_vss_log_info("%s: notify queue is empty!\n", __func__);
+ userdata->status = VSS_FAIL;
+ }
+ mtx_unlock(&dev_sc->sc->pending_mutex);
+}
+
+static void
+hv_vss_notify(struct hv_vss_dev_sc *dev_sc, struct hv_vss_req_internal *reqp)
+{
+ uint32_t opt = reqp->vss_req.opt_msg.opt;
+ mtx_lock(&dev_sc->sc->pending_mutex);
+ STAILQ_INSERT_TAIL(&dev_sc->to_notify_queue, reqp, slink);
+ hv_vss_log_info("%s: issuing query %s (%ju) to %s\n", __func__,
+ vss_opt_name[opt], (uintmax_t)reqp->vss_req.opt_msg.msgid,
+ &dev_sc->sc->app_sc == dev_sc ? "app" : "daemon");
+ mtx_unlock(&dev_sc->sc->pending_mutex);
+ selwakeup(&dev_sc->hv_vss_selinfo);
+}
+
+/**
+ * Actions for daemon who has acknowledged.
+ */
+static void
+hv_vss_daemon_acked(struct hv_vss_dev_sc *dev_sc, struct hv_vss_opt_msg *userdata)
+{
+ struct hv_vss_req_internal *reqp, *tmp;
+ uint64_t req_id;
+ int opt;
+ uint32_t status;
+
+ opt = userdata->opt;
+ req_id = userdata->msgid;
+ status = userdata->status;
+ /* make sure the reserved fields are all zeros. */
+ memset(&userdata->reserved, 0, sizeof(struct hv_vss_opt_msg) -
+ __offsetof(struct hv_vss_opt_msg, reserved));
+ mtx_lock(&dev_sc->sc->pending_mutex);
+ SEARCH_REMOVE_REQ_LOCKED(reqp, &dev_sc->to_ack_queue, slink, tmp, req_id);
+ mtx_unlock(&dev_sc->sc->pending_mutex);
+ if (reqp == NULL) {
+ hv_vss_log_info("%s Timeout: fail to find daemon ack request\n",
+ __func__);
+ userdata->status = VSS_FAIL;
+ return;
+ }
+ KASSERT(opt == reqp->vss_req.opt_msg.opt, ("Mismatched VSS operation!"));
+ hv_vss_log_info("%s, get response %d from daemon for %s (%ju) \n", __func__,
+ status, vss_opt_name[opt], (uintmax_t)req_id);
+ switch (opt) {
+ case HV_VSS_CHECK:
+ case HV_VSS_FREEZE:
+ callout_drain(&reqp->callout);
+ hv_vss_notify_host_result(reqp,
+ status == VSS_SUCCESS ? HV_S_OK : HV_E_FAIL);
+ break;
+ case HV_VSS_THAW:
+ if (dev_sc->sc->app_register_done) {
+ if (status == VSS_SUCCESS) {
+ hv_vss_notify(&dev_sc->sc->app_sc, reqp);
+ } else {
+ /* handle error */
+ callout_drain(&reqp->callout);
+ hv_vss_notify_host_result(reqp, HV_E_FAIL);
+ }
+ } else {
+ callout_drain(&reqp->callout);
+ hv_vss_notify_host_result(reqp,
+ status == VSS_SUCCESS ? HV_S_OK : HV_E_FAIL);
+ }
+ break;
+ }
+}
+
+/**
+ * Actions for app who has acknowledged.
+ */
+static void
+hv_vss_app_acked(struct hv_vss_dev_sc *dev_sc, struct hv_vss_opt_msg *userdata)
+{
+ struct hv_vss_req_internal *reqp, *tmp;
+ uint64_t req_id;
+ int opt;
+ uint8_t status;
+
+ opt = userdata->opt;
+ req_id = userdata->msgid;
+ status = userdata->status;
+ /* make sure the reserved fields are all zeros. */
+ memset(&userdata->reserved, 0, sizeof(struct hv_vss_opt_msg) -
+ __offsetof(struct hv_vss_opt_msg, reserved));
+ mtx_lock(&dev_sc->sc->pending_mutex);
+ SEARCH_REMOVE_REQ_LOCKED(reqp, &dev_sc->to_ack_queue, slink, tmp, req_id);
+ mtx_unlock(&dev_sc->sc->pending_mutex);
+ if (reqp == NULL) {
+ hv_vss_log_info("%s Timeout: fail to find app ack request\n",
+ __func__);
+ userdata->status = VSS_FAIL;
+ return;
+ }
+ KASSERT(opt == reqp->vss_req.opt_msg.opt, ("Mismatched VSS operation!"));
+ hv_vss_log_info("%s, get response %d from app for %s (%ju) \n",
+ __func__, status, vss_opt_name[opt], (uintmax_t)req_id);
+ if (dev_sc->sc->register_done) {
+ switch (opt) {
+ case HV_VSS_CHECK:
+ case HV_VSS_FREEZE:
+ if (status == VSS_SUCCESS) {
+ hv_vss_notify(&dev_sc->sc->daemon_sc, reqp);
+ } else {
+ /* handle error */
+ callout_drain(&reqp->callout);
+ hv_vss_notify_host_result(reqp, HV_E_FAIL);
+ }
+ break;
+ case HV_VSS_THAW:
+ callout_drain(&reqp->callout);
+ hv_vss_notify_host_result(reqp,
+ status == VSS_SUCCESS ? HV_S_OK : HV_E_FAIL);
+ break;
+ }
+ } else {
+ hv_vss_log_info("%s, Fatal: vss daemon was killed\n", __func__);
+ }
+}
+
+static int
+hv_vss_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct proc *td_proc;
+ td_proc = td->td_proc;
+
+ struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
+ hv_vss_log_info("%s: %s opens device \"%s\" successfully.\n",
+ __func__, td_proc->p_comm, FS_VSS_DEV_NAME);
+
+ if (dev_sc->sc->register_done)
+ return (EBUSY);
+
+ dev_sc->sc->register_done = true;
+ hv_vss_callback(vmbus_get_channel(dev_sc->sc->dev), dev_sc->sc);
+
+ dev_sc->proc_task = curproc;
+ return (0);
+}
+
+static int
+hv_vss_dev_close(struct cdev *dev, int fflag __unused, int devtype __unused,
+ struct thread *td)
+{
+ struct proc *td_proc;
+ td_proc = td->td_proc;
+
+ struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
+
+ hv_vss_log_info("%s: %s closes device \"%s\"\n",
+ __func__, td_proc->p_comm, FS_VSS_DEV_NAME);
+ dev_sc->sc->register_done = false;
+ return (0);
+}
+
+static int
+hv_vss_dev_daemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
+ struct thread *td)
+{
+ struct proc *td_proc;
+ struct hv_vss_dev_sc *sc;
+
+ td_proc = td->td_proc;
+ sc = (struct hv_vss_dev_sc*)dev->si_drv1;
+
+ hv_vss_log_info("%s: %s invoked vss ioctl\n", __func__, td_proc->p_comm);
+
+ struct hv_vss_opt_msg* userdata = (struct hv_vss_opt_msg*)data;
+ switch(cmd) {
+ case IOCHVVSSREAD:
+ hv_vss_notified(sc, userdata);
+ break;
+ case IOCHVVSSWRITE:
+ hv_vss_daemon_acked(sc, userdata);
+ break;
+ }
+ return (0);
+}
+
+/*
+ * hv_vss_daemon poll invokes this function to check if data is available
+ * for daemon to read.
+ */
+static int
+hv_vss_dev_daemon_poll(struct cdev *dev, int events, struct thread *td)
+{
+ int revent = 0;
+ struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
+
+ mtx_lock(&dev_sc->sc->pending_mutex);
+ /**
+ * if there is data ready, inform daemon's poll
+ */
+ if (!STAILQ_EMPTY(&dev_sc->to_notify_queue))
+ revent = POLLIN;
+ if (revent == 0)
+ selrecord(td, &dev_sc->hv_vss_selinfo);
+ hv_vss_log_info("%s return 0x%x\n", __func__, revent);
+ mtx_unlock(&dev_sc->sc->pending_mutex);
+ return (revent);
+}
+
+static int
+hv_appvss_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct proc *td_proc;
+ td_proc = td->td_proc;
+
+ struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
+ hv_vss_log_info("%s: %s opens device \"%s\" successfully.\n",
+ __func__, td_proc->p_comm, APP_VSS_DEV_NAME);
+
+ if (dev_sc->sc->app_register_done)
+ return (EBUSY);
+
+ dev_sc->sc->app_register_done = true;
+ dev_sc->proc_task = curproc;
+ return (0);
+}
+
+static int
+hv_appvss_dev_close(struct cdev *dev, int fflag __unused, int devtype __unused,
+ struct thread *td)
+{
+ struct proc *td_proc;
+ td_proc = td->td_proc;
+
+ struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
+
+ hv_vss_log_info("%s: %s closes device \"%s\".\n",
+ __func__, td_proc->p_comm, APP_VSS_DEV_NAME);
+ dev_sc->sc->app_register_done = false;
+ return (0);
+}
+
+static int
+hv_appvss_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
+ struct thread *td)
+{
+ struct proc *td_proc;
+ struct hv_vss_dev_sc *dev_sc;
+
+ td_proc = td->td_proc;
+ dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
+
+ hv_vss_log_info("%s: %s invoked vss ioctl\n", __func__, td_proc->p_comm);
+
+ struct hv_vss_opt_msg* userdata = (struct hv_vss_opt_msg*)data;
+ switch(cmd) {
+ case IOCHVVSSREAD:
+ hv_vss_notified(dev_sc, userdata);
+ break;
+ case IOCHVVSSWRITE:
+ hv_vss_app_acked(dev_sc, userdata);
+ break;
+ }
+ return (0);
+}
+
+/*
+ * hv_vss_daemon poll invokes this function to check if data is available
+ * for daemon to read.
+ */
+static int
+hv_appvss_dev_poll(struct cdev *dev, int events, struct thread *td)
+{
+ int revent = 0;
+ struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1;
+
+ mtx_lock(&dev_sc->sc->pending_mutex);
+ /**
+ * if there is data ready, inform daemon's poll
+ */
+ if (!STAILQ_EMPTY(&dev_sc->to_notify_queue))
+ revent = POLLIN;
+ if (revent == 0)
+ selrecord(td, &dev_sc->hv_vss_selinfo);
+ hv_vss_log_info("%s return 0x%x\n", __func__, revent);
+ mtx_unlock(&dev_sc->sc->pending_mutex);
+ return (revent);
+}
+
+static void
+hv_vss_timeout(void *arg)
+{
+ hv_vss_req_internal *reqp = arg;
+ hv_vss_req_internal *request;
+ hv_vss_sc* sc = reqp->sc;
+ uint64_t req_id = reqp->vss_req.opt_msg.msgid;
+ /* This thread is locked */
+ KASSERT(mtx_owned(&sc->pending_mutex), ("mutex lock is not owned!"));
+ request = hv_vss_drain_req_queue_locked(sc, req_id);
+ KASSERT(request != NULL, ("timeout but fail to find request"));
+ hv_vss_notify_host_result_locked(reqp, HV_E_FAIL);
+}
+
+/*
+ * This routine is called whenever a message is received from the host
+ */
+static void
+hv_vss_init_req(hv_vss_req_internal *reqp,
+ uint32_t recvlen, uint64_t requestid, uint8_t *vss_buf, hv_vss_sc *sc)
+{
+ struct timespec vm_ts;
+ struct hv_vss_msg* msg = (struct hv_vss_msg *)vss_buf;
+
+ memset(reqp, 0, __offsetof(hv_vss_req_internal, callout));
+ reqp->host_msg_len = recvlen;
+ reqp->host_msg_id = requestid;
+ reqp->rcv_buf = vss_buf;
+ reqp->sc = sc;
+ memcpy(&reqp->vss_req.msg,
+ (struct hv_vss_msg *)vss_buf, sizeof(struct hv_vss_msg));
+ /* set the opt for users */
+ switch (msg->hdr.vss_hdr.operation) {
+ case VSS_OP_FREEZE:
+ reqp->vss_req.opt_msg.opt = HV_VSS_FREEZE;
+ break;
+ case VSS_OP_THAW:
+ reqp->vss_req.opt_msg.opt = HV_VSS_THAW;
+ break;
+ case VSS_OP_HOT_BACKUP:
+ reqp->vss_req.opt_msg.opt = HV_VSS_CHECK;
+ break;
+ }
+ /* Use a timestamp as msg request ID */
+ nanotime(&vm_ts);
+ reqp->vss_req.opt_msg.msgid = (vm_ts.tv_sec * NANOSEC) + vm_ts.tv_nsec;
+}
+
+static hv_vss_req_internal*
+hv_vss_get_new_req_locked(hv_vss_sc *sc)
+{
+ hv_vss_req_internal *reqp;
+ if (!STAILQ_EMPTY(&sc->daemon_sc.to_notify_queue) ||
+ !STAILQ_EMPTY(&sc->daemon_sc.to_ack_queue) ||
+ !STAILQ_EMPTY(&sc->app_sc.to_notify_queue) ||
+ !STAILQ_EMPTY(&sc->app_sc.to_ack_queue)) {
+ /*
+ * There is request coming from host before
+ * finishing previous requests
+ */
+ hv_vss_log_info("%s: Warning: there is new request "
+ "coming before finishing previous requests\n", __func__);
+ return (NULL);
+ }
+ if (LIST_EMPTY(&sc->req_free_list)) {
+ /* TODO Error: no buffer */
+ hv_vss_log_info("Error: No buffer\n");
+ return (NULL);
+ }
+ reqp = LIST_FIRST(&sc->req_free_list);
+ LIST_REMOVE(reqp, link);
+ return (reqp);
+}
+
+static void
+hv_vss_start_notify(hv_vss_req_internal *reqp, uint32_t opt)
+{
+ hv_vss_sc *sc = reqp->sc;
+ /*
+ * Freeze/Check notification sequence: kernel -> app -> daemon(fs)
+ * Thaw notification sequence: kernel -> daemon(fs) -> app
+ *
+ * We should wake up the daemon, in case it's doing poll().
+ * The response should be received after 5s, otherwise, trigger timeout.
+ */
+ switch (opt) {
+ case VSS_OP_FREEZE:
+ case VSS_OP_HOT_BACKUP:
+ if (sc->app_register_done)
+ hv_vss_notify(&sc->app_sc, reqp);
+ else
+ hv_vss_notify(&sc->daemon_sc, reqp);
+ callout_reset(&reqp->callout, TIMEOUT_LIMIT * hz,
+ hv_vss_timeout, reqp);
+ break;
+ case VSS_OP_THAW:
+ hv_vss_notify(&sc->daemon_sc, reqp);
+ callout_reset(&reqp->callout, TIMEOUT_LIMIT * hz,
+ hv_vss_timeout, reqp);
+ break;
+ }
+}
+
+/*
+ * Function to read the vss request buffer from host
+ * and interact with daemon
+ */
+static void
+hv_vss_process_request(void *context, int pending __unused)
+{
+ uint8_t *vss_buf;
+ struct vmbus_channel *channel;
+ uint32_t recvlen = 0;
+ uint64_t requestid;
+ struct vmbus_icmsg_hdr *icmsghdrp;
+ int ret = 0;
+ hv_vss_sc *sc;
+ hv_vss_req_internal *reqp;
+
+ hv_vss_log_info("%s: entering hv_vss_process_request\n", __func__);
+
+ sc = (hv_vss_sc*)context;
+ vss_buf = sc->util_sc.receive_buffer;
+ channel = vmbus_get_channel(sc->dev);
+
+ recvlen = sc->util_sc.ic_buflen;
+ ret = vmbus_chan_recv(channel, vss_buf, &recvlen, &requestid);
+ KASSERT(ret != ENOBUFS, ("hvvss recvbuf is not large enough"));
+ /* XXX check recvlen to make sure that it contains enough data */
+
+ while ((ret == 0) && (recvlen > 0)) {
+ icmsghdrp = (struct vmbus_icmsg_hdr *)vss_buf;
+
+ if (icmsghdrp->ic_type == HV_ICMSGTYPE_NEGOTIATE) {
+ ret = vmbus_ic_negomsg(&sc->util_sc, vss_buf,
+ &recvlen, VSS_FWVER, VSS_MSGVER);
+ hv_vss_respond_host(vss_buf, vmbus_get_channel(sc->dev),
+ recvlen, requestid, ret);
+ hv_vss_log_info("%s: version negotiated\n", __func__);
+ } else if (!hv_vss_is_daemon_killed_after_launch(sc)) {
+ struct hv_vss_msg* msg = (struct hv_vss_msg *)vss_buf;
+ switch(msg->hdr.vss_hdr.operation) {
+ case VSS_OP_FREEZE:
+ case VSS_OP_THAW:
+ case VSS_OP_HOT_BACKUP:
+ mtx_lock(&sc->pending_mutex);
+ reqp = hv_vss_get_new_req_locked(sc);
+ mtx_unlock(&sc->pending_mutex);
+ if (reqp == NULL) {
+ /* ignore this request from host */
+ break;
+ }
+ hv_vss_init_req(reqp, recvlen, requestid, vss_buf, sc);
+ hv_vss_log_info("%s: receive %s (%ju) from host\n",
+ __func__,
+ vss_opt_name[reqp->vss_req.opt_msg.opt],
+ (uintmax_t)reqp->vss_req.opt_msg.msgid);
+ hv_vss_start_notify(reqp, msg->hdr.vss_hdr.operation);
+ break;
+ case VSS_OP_GET_DM_INFO:
+ hv_vss_log_info("%s: receive GET_DM_INFO from host\n",
+ __func__);
+ msg->body.dm_info.flags = 0;
+ hv_vss_respond_host(vss_buf, vmbus_get_channel(sc->dev),
+ recvlen, requestid, HV_S_OK);
+ break;
+ default:
+ device_printf(sc->dev, "Unknown opt from host: %d\n",
+ msg->hdr.vss_hdr.operation);
+ break;
+ }
+ } else {
+ /* daemon was killed for some reason after it was launched */
+ struct hv_vss_msg* msg = (struct hv_vss_msg *)vss_buf;
+ switch(msg->hdr.vss_hdr.operation) {
+ case VSS_OP_FREEZE:
+ hv_vss_log_info("%s: response fail for FREEZE\n",
+ __func__);
+ break;
+ case VSS_OP_THAW:
+ hv_vss_log_info("%s: response fail for THAW\n",
+ __func__);
+ break;
+ case VSS_OP_HOT_BACKUP:
+ hv_vss_log_info("%s: response fail for HOT_BACKUP\n",
+ __func__);
+ msg->body.vss_cf.flags = VSS_HBU_NO_AUTO_RECOVERY;
+ break;
+ case VSS_OP_GET_DM_INFO:
+ hv_vss_log_info("%s: response fail for GET_DM_INFO\n",
+ __func__);
+ msg->body.dm_info.flags = 0;
+ break;
+ default:
+ device_printf(sc->dev, "Unknown opt from host: %d\n",
+ msg->hdr.vss_hdr.operation);
+ break;
+ }
+ hv_vss_respond_host(vss_buf, vmbus_get_channel(sc->dev),
+ recvlen, requestid, HV_E_FAIL);
+ }
+ /*
+ * Try reading next buffer
+ */
+ recvlen = sc->util_sc.ic_buflen;
+ ret = vmbus_chan_recv(channel, vss_buf, &recvlen, &requestid);
+ KASSERT(ret != ENOBUFS, ("hvvss recvbuf is not large enough"));
+ /* XXX check recvlen to make sure that it contains enough data */
+
+ hv_vss_log_info("%s: read: context %p, ret =%d, recvlen=%d\n",
+ __func__, context, ret, recvlen);
+ }
+}
+
+static int
+hv_vss_probe(device_t dev)
+{
+ return (vmbus_ic_probe(dev, vmbus_vss_descs));
+}
+
+static int
+hv_vss_init_send_receive_queue(device_t dev)
+{
+ hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev);
+ int i;
+ const int max_list = 4; /* It is big enough for the list */
+ struct hv_vss_req_internal* reqp;
+
+ LIST_INIT(&sc->req_free_list);
+ STAILQ_INIT(&sc->daemon_sc.to_notify_queue);
+ STAILQ_INIT(&sc->daemon_sc.to_ack_queue);
+ STAILQ_INIT(&sc->app_sc.to_notify_queue);
+ STAILQ_INIT(&sc->app_sc.to_ack_queue);
+
+ for (i = 0; i < max_list; i++) {
+ reqp = malloc(sizeof(struct hv_vss_req_internal),
+ M_DEVBUF, M_WAITOK|M_ZERO);
+ LIST_INSERT_HEAD(&sc->req_free_list, reqp, link);
+ callout_init_mtx(&reqp->callout, &sc->pending_mutex, 0);
+ }
+ return (0);
+}
+
+static int
+hv_vss_destroy_send_receive_queue(device_t dev)
+{
+ hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev);
+ hv_vss_req_internal* reqp;
+
+ while (!LIST_EMPTY(&sc->req_free_list)) {
+ reqp = LIST_FIRST(&sc->req_free_list);
+ LIST_REMOVE(reqp, link);
+ free(reqp, M_DEVBUF);
+ }
+
+ while (!STAILQ_EMPTY(&sc->daemon_sc.to_notify_queue)) {
+ reqp = STAILQ_FIRST(&sc->daemon_sc.to_notify_queue);
+ STAILQ_REMOVE_HEAD(&sc->daemon_sc.to_notify_queue, slink);
+ free(reqp, M_DEVBUF);
+ }
+
+ while (!STAILQ_EMPTY(&sc->daemon_sc.to_ack_queue)) {
+ reqp = STAILQ_FIRST(&sc->daemon_sc.to_ack_queue);
+ STAILQ_REMOVE_HEAD(&sc->daemon_sc.to_ack_queue, slink);
+ free(reqp, M_DEVBUF);
+ }
+
+ while (!STAILQ_EMPTY(&sc->app_sc.to_notify_queue)) {
+ reqp = STAILQ_FIRST(&sc->app_sc.to_notify_queue);
+ STAILQ_REMOVE_HEAD(&sc->app_sc.to_notify_queue, slink);
+ free(reqp, M_DEVBUF);
+ }
+
+ while (!STAILQ_EMPTY(&sc->app_sc.to_ack_queue)) {
+ reqp = STAILQ_FIRST(&sc->app_sc.to_ack_queue);
+ STAILQ_REMOVE_HEAD(&sc->app_sc.to_ack_queue, slink);
+ free(reqp, M_DEVBUF);
+ }
+ return (0);
+}
+
+static int
+hv_vss_attach(device_t dev)
+{
+ int error;
+ struct sysctl_oid_list *child;
+ struct sysctl_ctx_list *ctx;
+
+ hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev);
+
+ sc->dev = dev;
+ mtx_init(&sc->pending_mutex, "hv_vss pending mutex", NULL, MTX_DEF);
+
+ ctx = device_get_sysctl_ctx(dev);
+ child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
+
+ SYSCTL_ADD_INT(ctx, child, OID_AUTO, "hv_vss_log",
+ CTLFLAG_RWTUN, &hv_vss_log, 0, "Hyperv VSS service log level");
+
+ TASK_INIT(&sc->task, 0, hv_vss_process_request, sc);
+ hv_vss_init_send_receive_queue(dev);
+ /* create character device for file system freeze/thaw */
+ error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
+ &sc->hv_vss_dev,
+ &hv_vss_cdevsw,
+ 0,
+ UID_ROOT,
+ GID_WHEEL,
+ 0640,
+ FS_VSS_DEV_NAME);
+
+ if (error != 0) {
+ hv_vss_log_info("Fail to create '%s': %d\n", FS_VSS_DEV_NAME, error);
+ return (error);
+ }
+ sc->hv_vss_dev->si_drv1 = &sc->daemon_sc;
+ sc->daemon_sc.sc = sc;
+ /* create character device for application freeze/thaw */
+ error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
+ &sc->hv_appvss_dev,
+ &hv_appvss_cdevsw,
+ 0,
+ UID_ROOT,
+ GID_WHEEL,
+ 0640,
+ APP_VSS_DEV_NAME);
+
+ if (error != 0) {
+ hv_vss_log_info("Fail to create '%s': %d\n", APP_VSS_DEV_NAME, error);
+ return (error);
+ }
+ sc->hv_appvss_dev->si_drv1 = &sc->app_sc;
+ sc->app_sc.sc = sc;
+
+ return hv_util_attach(dev, hv_vss_callback);
+}
+
+static int
+hv_vss_detach(device_t dev)
+{
+ hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev);
+ mtx_destroy(&sc->pending_mutex);
+ if (sc->daemon_sc.proc_task != NULL) {
+ PROC_LOCK(sc->daemon_sc.proc_task);
+ kern_psignal(sc->daemon_sc.proc_task, SIGKILL);
+ PROC_UNLOCK(sc->daemon_sc.proc_task);
+ }
+ if (sc->app_sc.proc_task != NULL) {
+ PROC_LOCK(sc->app_sc.proc_task);
+ kern_psignal(sc->app_sc.proc_task, SIGKILL);
+ PROC_UNLOCK(sc->app_sc.proc_task);
+ }
+ hv_vss_destroy_send_receive_queue(dev);
+ destroy_dev(sc->hv_vss_dev);
+ destroy_dev(sc->hv_appvss_dev);
+ return hv_util_detach(dev);
+}
+
+static device_method_t vss_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, hv_vss_probe),
+ DEVMETHOD(device_attach, hv_vss_attach),
+ DEVMETHOD(device_detach, hv_vss_detach),
+ { 0, 0 }
+};
+
+static driver_t vss_driver = { "hvvss", vss_methods, sizeof(hv_vss_sc)};
+
+static devclass_t vss_devclass;
+
+DRIVER_MODULE(hv_vss, vmbus, vss_driver, vss_devclass, NULL, NULL);
+MODULE_VERSION(hv_vss, 1);
+MODULE_DEPEND(hv_vss, vmbus, 1, 1, 1);
diff --git a/sys/dev/hyperv/utilities/hv_snapshot.h b/sys/dev/hyperv/utilities/hv_snapshot.h
new file mode 100644
index 000000000000..e3c9e0c9fef2
--- /dev/null
+++ b/sys/dev/hyperv/utilities/hv_snapshot.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2016 Microsoft Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VSS_H
+#define _VSS_H
+#include <sys/ioccom.h>
+#define FS_VSS_DEV_NAME "hv_fsvss_dev"
+#define APP_VSS_DEV_NAME "hv_appvss_dev"
+
+#define VSS_DEV(VSS) "/dev/"VSS
+
+#define VSS_SUCCESS 0x00000000
+#define VSS_FAIL 0x00000001
+
+enum hv_vss_op_t {
+ HV_VSS_NONE = 0,
+ HV_VSS_CHECK,
+ HV_VSS_FREEZE,
+ HV_VSS_THAW,
+ HV_VSS_COUNT
+};
+
+struct hv_vss_opt_msg {
+ uint32_t opt; /* operation */
+ uint32_t status; /* 0 for success, 1 for error */
+ uint64_t msgid; /* an ID used to identify the transaction */
+ uint8_t reserved[48]; /* reserved values are all zeroes */
+};
+#define IOCHVVSSREAD _IOR('v', 2, struct hv_vss_opt_msg)
+#define IOCHVVSSWRITE _IOW('v', 3, struct hv_vss_opt_msg)
+#endif
diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c
index 11be35ba4d73..4695d9572574 100644
--- a/sys/dev/hyperv/vmbus/vmbus.c
+++ b/sys/dev/hyperv/vmbus/vmbus.c
@@ -44,10 +44,13 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/taskqueue.h>
+#include <machine/bus.h>
#include <machine/intr_machdep.h>
+#include <machine/resource.h>
#include <x86/include/apicvar.h>
#include <contrib/dev/acpica/include/acpi.h>
+#include <dev/acpica/acpivar.h>
#include <dev/hyperv/include/hyperv.h>
#include <dev/hyperv/include/vmbus_xact.h>
@@ -58,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <dev/hyperv/vmbus/vmbus_chanvar.h>
#include "acpi_if.h"
+#include "pcib_if.h"
#include "vmbus_if.h"
#define VMBUS_GPADL_START 0xe1e10
@@ -74,9 +78,25 @@ static int vmbus_read_ivar(device_t, device_t, int,
uintptr_t *);
static int vmbus_child_pnpinfo_str(device_t, device_t,
char *, size_t);
+static struct resource *vmbus_alloc_resource(device_t dev,
+ device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end,
+ rman_res_t count, u_int flags);
+static int vmbus_alloc_msi(device_t bus, device_t dev,
+ int count, int maxcount, int *irqs);
+static int vmbus_release_msi(device_t bus, device_t dev,
+ int count, int *irqs);
+static int vmbus_alloc_msix(device_t bus, device_t dev,
+ int *irq);
+static int vmbus_release_msix(device_t bus, device_t dev,
+ int irq);
+static int vmbus_map_msi(device_t bus, device_t dev,
+ int irq, uint64_t *addr, uint32_t *data);
static uint32_t vmbus_get_version_method(device_t, device_t);
static int vmbus_probe_guid_method(device_t, device_t,
const struct hyperv_guid *);
+static uint32_t vmbus_get_vcpu_id_method(device_t bus,
+ device_t dev, int cpu);
static int vmbus_init(struct vmbus_softc *);
static int vmbus_connect(struct vmbus_softc *, uint32_t);
@@ -131,10 +151,27 @@ static device_method_t vmbus_methods[] = {
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, vmbus_read_ivar),
DEVMETHOD(bus_child_pnpinfo_str, vmbus_child_pnpinfo_str),
+ DEVMETHOD(bus_alloc_resource, vmbus_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+#if __FreeBSD_version >= 1100000
+ DEVMETHOD(bus_get_cpus, bus_generic_get_cpus),
+#endif
+
+ /* pcib interface */
+ DEVMETHOD(pcib_alloc_msi, vmbus_alloc_msi),
+ DEVMETHOD(pcib_release_msi, vmbus_release_msi),
+ DEVMETHOD(pcib_alloc_msix, vmbus_alloc_msix),
+ DEVMETHOD(pcib_release_msix, vmbus_release_msix),
+ DEVMETHOD(pcib_map_msi, vmbus_map_msi),
/* Vmbus interface */
DEVMETHOD(vmbus_get_version, vmbus_get_version_method),
DEVMETHOD(vmbus_probe_guid, vmbus_probe_guid_method),
+ DEVMETHOD(vmbus_get_vcpu_id, vmbus_get_vcpu_id_method),
DEVMETHOD_END
};
@@ -149,6 +186,7 @@ static devclass_t vmbus_devclass;
DRIVER_MODULE(vmbus, acpi, vmbus_driver, vmbus_devclass, NULL, NULL);
MODULE_DEPEND(vmbus, acpi, 1, 1, 1);
+MODULE_DEPEND(vmbus, pci, 1, 1, 1);
MODULE_VERSION(vmbus, 1);
static __inline struct vmbus_softc *
@@ -972,6 +1010,69 @@ vmbus_sysctl_version(SYSCTL_HANDLER_ARGS)
return sysctl_handle_string(oidp, verstr, sizeof(verstr), req);
}
+/*
+ * We need the function to make sure the MMIO resource is allocated from the
+ * ranges found in _CRS.
+ *
+ * For the release function, we can use bus_generic_release_resource().
+ */
+static struct resource *
+vmbus_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+ struct vmbus_softc *sc = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+ struct resource *res;
+
+ if (type != SYS_RES_MEMORY)
+ res = BUS_ALLOC_RESOURCE(parent, child, type, rid, start,
+ end, count, flags);
+ else
+ res = pcib_host_res_alloc(&sc->vmbus_mmio_res, child, type,
+ rid, start, end, count, flags);
+
+ return (res);
+}
+
+static device_t
+get_nexus(device_t vmbus)
+{
+ device_t acpi = device_get_parent(vmbus);
+ device_t nexus = device_get_parent(acpi);
+ return (nexus);
+}
+
+static int
+vmbus_alloc_msi(device_t bus, device_t dev, int count, int maxcount, int *irqs)
+{
+ return (PCIB_ALLOC_MSI(get_nexus(bus), dev, count, maxcount, irqs));
+}
+
+static int
+vmbus_release_msi(device_t bus, device_t dev, int count, int *irqs)
+{
+ return (PCIB_RELEASE_MSI(get_nexus(bus), dev, count, irqs));
+}
+
+static int
+vmbus_alloc_msix(device_t bus, device_t dev, int *irq)
+{
+ return (PCIB_ALLOC_MSIX(get_nexus(bus), dev, irq));
+}
+
+static int
+vmbus_release_msix(device_t bus, device_t dev, int irq)
+{
+ return (PCIB_RELEASE_MSIX(get_nexus(bus), dev, irq));
+}
+
+static int
+vmbus_map_msi(device_t bus, device_t dev, int irq, uint64_t *addr,
+ uint32_t *data)
+{
+ return (PCIB_MAP_MSI(get_nexus(bus), dev, irq, addr, data));
+}
+
static uint32_t
vmbus_get_version_method(device_t bus, device_t dev)
{
@@ -991,6 +1092,146 @@ vmbus_probe_guid_method(device_t bus, device_t dev,
return ENXIO;
}
+static uint32_t
+vmbus_get_vcpu_id_method(device_t bus, device_t dev, int cpu)
+{
+ const struct vmbus_softc *sc = device_get_softc(bus);
+
+ return (VMBUS_PCPU_GET(sc, vcpuid, cpu));
+}
+
+#define VTPM_BASE_ADDR 0xfed40000
+#define FOUR_GB (1ULL << 32)
+
+enum parse_pass { parse_64, parse_32 };
+
+struct parse_context {
+ device_t vmbus_dev;
+ enum parse_pass pass;
+};
+
+static ACPI_STATUS
+parse_crs(ACPI_RESOURCE *res, void *ctx)
+{
+ const struct parse_context *pc = ctx;
+ device_t vmbus_dev = pc->vmbus_dev;
+
+ struct vmbus_softc *sc = device_get_softc(vmbus_dev);
+ UINT64 start, end;
+
+ switch (res->Type) {
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ start = res->Data.Address32.Address.Minimum;
+ end = res->Data.Address32.Address.Maximum;
+ break;
+
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ start = res->Data.Address64.Address.Minimum;
+ end = res->Data.Address64.Address.Maximum;
+ break;
+
+ default:
+ /* Unused types. */
+ return (AE_OK);
+ }
+
+ /*
+ * We don't use <1MB addresses.
+ */
+ if (end < 0x100000)
+ return (AE_OK);
+
+ /* Don't conflict with vTPM. */
+ if (end >= VTPM_BASE_ADDR && start < VTPM_BASE_ADDR)
+ end = VTPM_BASE_ADDR - 1;
+
+ if ((pc->pass == parse_32 && start < FOUR_GB) ||
+ (pc->pass == parse_64 && start >= FOUR_GB))
+ pcib_host_res_decodes(&sc->vmbus_mmio_res, SYS_RES_MEMORY,
+ start, end, 0);
+
+ return (AE_OK);
+}
+
+static void
+vmbus_get_crs(device_t dev, device_t vmbus_dev, enum parse_pass pass)
+{
+ struct parse_context pc;
+ ACPI_STATUS status;
+
+ if (bootverbose)
+ device_printf(dev, "walking _CRS, pass=%d\n", pass);
+
+ pc.vmbus_dev = vmbus_dev;
+ pc.pass = pass;
+ status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
+ parse_crs, &pc);
+
+ if (bootverbose && ACPI_FAILURE(status))
+ device_printf(dev, "_CRS: not found, pass=%d\n", pass);
+}
+
+static void
+vmbus_get_mmio_res_pass(device_t dev, enum parse_pass pass)
+{
+ device_t acpi0, pcib0 = NULL;
+ device_t *children;
+ int i, count;
+
+ /* Try to find _CRS on VMBus device */
+ vmbus_get_crs(dev, dev, pass);
+
+ /* Try to find _CRS on VMBus device's parent */
+ acpi0 = device_get_parent(dev);
+ vmbus_get_crs(acpi0, dev, pass);
+
+ /* Try to locate pcib0 and find _CRS on it */
+ if (device_get_children(acpi0, &children, &count) != 0)
+ return;
+
+ for (i = 0; i < count; i++) {
+ if (!device_is_attached(children[i]))
+ continue;
+
+ if (strcmp("pcib0", device_get_nameunit(children[i])))
+ continue;
+
+ pcib0 = children[i];
+ break;
+ }
+
+ if (pcib0)
+ vmbus_get_crs(pcib0, dev, pass);
+
+ free(children, M_TEMP);
+}
+
+static void
+vmbus_get_mmio_res(device_t dev)
+{
+ struct vmbus_softc *sc = device_get_softc(dev);
+ /*
+ * We walk the resources twice to make sure that: in the resource
+ * list, the 32-bit resources appear behind the 64-bit resources.
+ * NB: resource_list_add() uses INSERT_TAIL. This way, when we
+ * iterate through the list to find a range for a 64-bit BAR in
+ * vmbus_alloc_resource(), we can make sure we try to use >4GB
+ * ranges first.
+ */
+ pcib_host_res_init(dev, &sc->vmbus_mmio_res);
+
+ vmbus_get_mmio_res_pass(dev, parse_64);
+ vmbus_get_mmio_res_pass(dev, parse_32);
+}
+
+static void
+vmbus_free_mmio_res(device_t dev)
+{
+ struct vmbus_softc *sc = device_get_softc(dev);
+
+ pcib_host_res_free(dev, &sc->vmbus_mmio_res);
+}
+
static int
vmbus_probe(device_t dev)
{
@@ -1027,6 +1268,9 @@ vmbus_doattach(struct vmbus_softc *sc)
if (sc->vmbus_flags & VMBUS_FLAG_ATTACHED)
return (0);
+
+ vmbus_get_mmio_res(sc->vmbus_dev);
+
sc->vmbus_flags |= VMBUS_FLAG_ATTACHED;
sc->vmbus_gpadl = VMBUS_GPADL_START;
@@ -1173,6 +1417,8 @@ vmbus_detach(device_t dev)
mtx_destroy(&sc->vmbus_prichan_lock);
mtx_destroy(&sc->vmbus_chan_lock);
+ vmbus_free_mmio_res(dev);
+
return (0);
}
diff --git a/sys/dev/hyperv/vmbus/vmbus_if.m b/sys/dev/hyperv/vmbus/vmbus_if.m
index 592f45f5d88c..65de846eb6be 100644
--- a/sys/dev/hyperv/vmbus/vmbus_if.m
+++ b/sys/dev/hyperv/vmbus/vmbus_if.m
@@ -45,3 +45,9 @@ METHOD int probe_guid {
device_t dev;
const struct hyperv_guid *guid;
};
+
+METHOD uint32_t get_vcpu_id {
+ device_t bus;
+ device_t dev;
+ int cpu;
+};
diff --git a/sys/dev/hyperv/vmbus/vmbus_var.h b/sys/dev/hyperv/vmbus/vmbus_var.h
index df4553a9e401..7aa035f94d85 100644
--- a/sys/dev/hyperv/vmbus/vmbus_var.h
+++ b/sys/dev/hyperv/vmbus/vmbus_var.h
@@ -31,8 +31,11 @@
#include <sys/param.h>
#include <sys/taskqueue.h>
+#include <sys/rman.h>
#include <dev/hyperv/include/hyperv_busdma.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcib_private.h>
/*
* NOTE: DO NOT CHANGE THIS.
@@ -77,6 +80,10 @@ struct vmbus_pcpu_data {
struct task message_task; /* message task */
} __aligned(CACHE_LINE_SIZE);
+#if __FreeBSD_version < 1100000
+typedef u_long rman_res_t;
+#endif
+
struct vmbus_softc {
void (*vmbus_event_proc)(struct vmbus_softc *, int);
u_long *vmbus_tx_evtflags;
@@ -120,6 +127,9 @@ struct vmbus_softc {
/* Complete channel list */
struct mtx vmbus_chan_lock;
TAILQ_HEAD(, vmbus_channel) vmbus_chans;
+
+ /* The list of usable MMIO ranges for PCIe pass-through */
+ struct pcib_host_resources vmbus_mmio_res;
};
#define VMBUS_FLAG_ATTACHED 0x0001 /* vmbus was attached */
diff --git a/sys/dev/ic/ns16550.h b/sys/dev/ic/ns16550.h
index e4c714f21463..29a73a018619 100644
--- a/sys/dev/ic/ns16550.h
+++ b/sys/dev/ic/ns16550.h
@@ -45,8 +45,13 @@
#define IER_ETXRDY 0x2
#define IER_ERLS 0x4
#define IER_EMSC 0x8
+/*
+ * Receive timeout interrupt enable.
+ * Implemented in Intel XScale, Ingenic XBurst.
+ */
+#define IER_RXTMOUT 0x10
-#define IER_BITS "\20\1ERXRDY\2ETXRDY\3ERLS\4EMSC"
+#define IER_BITS "\20\1ERXRDY\2ETXRDY\3ERLS\4EMSC\5RXTMOUT"
#define com_iir 2 /* interrupt identification register (R) */
#define REG_IIR com_iir
@@ -156,6 +161,9 @@
#define FIFO_XMT_RST FCR_XMT_RST
#define FCR_DMA 0x08
#define FIFO_DMA_MODE FCR_DMA
+#ifdef CPU_XBURST
+#define FCR_UART_ON 0x10
+#endif
#define FCR_RX_LOW 0x00
#define FIFO_RX_LOW FCR_RX_LOW
#define FCR_RX_MEDL 0x40
diff --git a/sys/dev/iicbus/iicsmb.c b/sys/dev/iicbus/iicsmb.c
index b49d93d56efa..88af163d2fe2 100644
--- a/sys/dev/iicbus/iicsmb.c
+++ b/sys/dev/iicbus/iicsmb.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <dev/iicbus/iiconf.h>
#include <dev/iicbus/iicbus.h>
+#include <dev/smbus/smb.h>
#include <dev/smbus/smbconf.h>
#include "iicbus_if.h"
@@ -432,7 +433,7 @@ iicsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
};
int error;
- if (count > 32 || count == 0)
+ if (count > SMB_MAXBLOCKSIZE || count == 0)
return (SMB_EINVAL);
error = TRANSFER_MSGS(dev, msgs);
return (iic2smb_error(error));
@@ -450,12 +451,6 @@ iicsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
};
device_t parent = device_get_parent(dev);
int error;
- u_char bufsz;
-
- /* Stash output buffer size before overwriting it. */
- bufsz = *count;
- if (bufsz == 0)
- return (SMB_EINVAL);
/* Have to do this because the command is split in two transfers. */
error = iicbus_request_bus(parent, dev, IIC_WAIT);
@@ -465,18 +460,13 @@ iicsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
/*
* If the slave offers an empty or a too long reply,
* read one byte to generate the stop or abort.
- * XXX 32 is hardcoded until SMB_MAXBLOCKSIZE is restored
- * to sanity.
*/
- if (*count > 32 || *count == 0)
+ if (*count > SMB_MAXBLOCKSIZE || *count == 0)
block_msg[0].len = 1;
- /* If longer than the buffer, then clamp at the buffer size. */
- if (*count > bufsz)
- block_msg[0].len = bufsz;
else
block_msg[0].len = *count;
error = TRANSFER_MSGS(dev, block_msg);
- if (*count > 32 || *count == 0)
+ if (*count > SMB_MAXBLOCKSIZE || *count == 0)
error = SMB_EINVAL;
}
(void)iicbus_release_bus(parent, dev);
diff --git a/sys/dev/intpm/intpm.c b/sys/dev/intpm/intpm.c
index bab2a7b73cfc..bcb3d6dd1bce 100644
--- a/sys/dev/intpm/intpm.c
+++ b/sys/dev/intpm/intpm.c
@@ -785,39 +785,11 @@ intsmb_readw(device_t dev, u_char slave, char cmd, short *word)
return (error);
}
-/*
- * Data sheet claims that it implements all function, but also claims
- * that it implements 7 function and not mention PCALL. So I don't know
- * whether it will work.
- */
static int
intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata)
{
-#ifdef PROCCALL_TEST
- struct intsmb_softc *sc = device_get_softc(dev);
- int error;
- INTSMB_LOCK(sc);
- error = intsmb_free(sc);
- if (error) {
- INTSMB_UNLOCK(sc);
- return (error);
- }
- bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB);
- bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
- bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, sdata & 0xff);
- bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (sdata & 0xff) >> 8);
- intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0);
- error = intsmb_stop(sc);
- if (error == 0) {
- *rdata = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
- *rdata |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8;
- }
- INTSMB_UNLOCK(sc);
- return (error);
-#else
return (SMB_ENOTSUPP);
-#endif
}
static int
@@ -857,9 +829,6 @@ intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
int error, i;
u_char data, nread;
- if (*count > SMBBLOCKTRANS_MAX || *count == 0)
- return (SMB_EINVAL);
-
INTSMB_LOCK(sc);
error = intsmb_free(sc);
if (error) {
@@ -872,18 +841,14 @@ intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB);
bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
- bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, *count);
intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0);
error = intsmb_stop(sc);
if (error == 0) {
nread = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
if (nread != 0 && nread <= SMBBLOCKTRANS_MAX) {
- for (i = 0; i < nread; i++) {
- data = bus_read_1(sc->io_res, PIIX4_SMBBLKDAT);
- if (i < *count)
- buf[i] = data;
- }
*count = nread;
+ for (i = 0; i < nread; i++)
+ data = bus_read_1(sc->io_res, PIIX4_SMBBLKDAT);
} else
error = SMB_EBUSERR;
}
diff --git a/sys/dev/ioat/ioat.c b/sys/dev/ioat/ioat.c
index a434b4225348..b7a2b44327de 100644
--- a/sys/dev/ioat/ioat.c
+++ b/sys/dev/ioat/ioat.c
@@ -765,6 +765,15 @@ out:
mtx_lock(&ioat->submit_lock);
mtx_lock(&ioat->cleanup_lock);
ioat->quiescing = TRUE;
+ /*
+ * This is safe to do here because we have both locks and the submit
+ * queue is quiesced. We know that we will drain all outstanding
+ * events, so ioat_reset_hw can't deadlock. It is necessary to
+ * protect other ioat_process_event threads from racing ioat_reset_hw,
+ * reading an indeterminate hw state, and attempting to continue
+ * issuing completions.
+ */
+ ioat->resetting_cleanup = TRUE;
chanerr = ioat_read_4(ioat, IOAT_CHANERR_OFFSET);
if (1 <= g_ioat_debug_level)
diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c
index 854c9e5a697d..c61857453a36 100644
--- a/sys/dev/iwm/if_iwm.c
+++ b/sys/dev/iwm/if_iwm.c
@@ -1666,8 +1666,10 @@ const int nvm_to_read[] = {
#define IWM_NVM_READ_OPCODE 0
/* load nvm chunk response */
-#define IWM_READ_NVM_CHUNK_SUCCEED 0
-#define IWM_READ_NVM_CHUNK_INVALID_ADDRESS 1
+enum {
+ IWM_READ_NVM_CHUNK_SUCCEED = 0,
+ IWM_READ_NVM_CHUNK_NOT_VALID_ADDRESS = 1
+};
static int
iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section,
@@ -1684,12 +1686,10 @@ iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section,
struct iwm_rx_packet *pkt;
struct iwm_host_cmd cmd = {
.id = IWM_NVM_ACCESS_CMD,
- .flags = IWM_CMD_SYNC | IWM_CMD_WANT_SKB |
- IWM_CMD_SEND_IN_RFKILL,
+ .flags = IWM_CMD_WANT_SKB | IWM_CMD_SEND_IN_RFKILL,
.data = { &nvm_access_cmd, },
};
- int ret, offset_read;
- size_t bytes_read;
+ int ret, bytes_read, offset_read;
uint8_t *resp_data;
cmd.len[0] = sizeof(struct iwm_nvm_access_cmd);
@@ -1718,9 +1718,26 @@ iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section,
offset_read = le16toh(nvm_resp->offset);
resp_data = nvm_resp->data;
if (ret) {
- IWM_DPRINTF(sc, IWM_DEBUG_RESET,
- "NVM access command failed with status %d\n", ret);
- ret = EINVAL;
+ if ((offset != 0) &&
+ (ret == IWM_READ_NVM_CHUNK_NOT_VALID_ADDRESS)) {
+ /*
+ * meaning of NOT_VALID_ADDRESS:
+ * driver try to read chunk from address that is
+ * multiple of 2K and got an error since addr is empty.
+ * meaning of (offset != 0): driver already
+ * read valid data from another chunk so this case
+ * is not an error.
+ */
+ IWM_DPRINTF(sc, IWM_DEBUG_EEPROM | IWM_DEBUG_RESET,
+ "NVM access command failed on offset 0x%x since that section size is multiple 2K\n",
+ offset);
+ *len = 0;
+ ret = 0;
+ } else {
+ IWM_DPRINTF(sc, IWM_DEBUG_EEPROM | IWM_DEBUG_RESET,
+ "NVM access command failed with status %d\n", ret);
+ ret = EIO;
+ }
goto exit;
}
@@ -1735,7 +1752,7 @@ iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section,
if (bytes_read > length) {
device_printf(sc->sc_dev,
"NVM ACCESS response with too much data "
- "(%d bytes requested, %zd bytes received)\n",
+ "(%d bytes requested, %d bytes received)\n",
length, bytes_read);
ret = EINVAL;
goto exit;
@@ -6192,7 +6209,8 @@ iwm_detach_local(struct iwm_softc *sc, int do_net80211)
device_t dev = sc->sc_dev;
int i;
- ieee80211_draintask(&sc->sc_ic, &sc->sc_es_task);
+ if (do_net80211)
+ ieee80211_draintask(&sc->sc_ic, &sc->sc_es_task);
callout_drain(&sc->sc_led_blink_to);
callout_drain(&sc->sc_watchdog_to);
diff --git a/sys/dev/kbdmux/kbdmux.c b/sys/dev/kbdmux/kbdmux.c
index 4720a0e6fc88..9a80760a8730 100644
--- a/sys/dev/kbdmux/kbdmux.c
+++ b/sys/dev/kbdmux/kbdmux.c
@@ -32,6 +32,7 @@
*/
#include "opt_compat.h"
+#include "opt_evdev.h"
#include "opt_kbd.h"
#include "opt_kbdmux.h"
@@ -64,6 +65,11 @@
#include <dev/kbd/kbdtables.h>
+#ifdef EVDEV_SUPPORT
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/input.h>
+#endif
+
#define KEYBOARD_NAME "kbdmux"
MALLOC_DECLARE(M_KBDMUX);
@@ -159,6 +165,11 @@ struct kbdmux_state
u_int ks_composed_char; /* composed char code */
u_char ks_prefix; /* AT scan code prefix */
+#ifdef EVDEV_SUPPORT
+ struct evdev_dev * ks_evdev;
+ int ks_evdev_state;
+#endif
+
SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
KBDMUX_LOCK_DECL_GLOBAL;
@@ -371,6 +382,12 @@ static keyboard_switch_t kbdmuxsw = {
.diag = genkbd_diag,
};
+#ifdef EVDEV_SUPPORT
+static const struct evdev_methods kbdmux_evdev_methods = {
+ .ev_event = evdev_ev_kbd_event,
+};
+#endif
+
/*
* Return the number of found keyboards
*/
@@ -404,6 +421,10 @@ kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
accentmap_t *accmap = NULL;
fkeytab_t *fkeymap = NULL;
int error, needfree, fkeymap_size, delay[2];
+#ifdef EVDEV_SUPPORT
+ struct evdev_dev *evdev;
+ char phys_loc[NAMELEN];
+#endif
if (*kbdp == NULL) {
*kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
@@ -464,6 +485,30 @@ kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
delay[1] = kbd->kb_delay2;
kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
+#ifdef EVDEV_SUPPORT
+ /* register as evdev provider */
+ evdev = evdev_alloc();
+ evdev_set_name(evdev, "System keyboard multiplexer");
+ snprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit);
+ evdev_set_phys(evdev, phys_loc);
+ evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0);
+ evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods);
+ evdev_support_event(evdev, EV_SYN);
+ evdev_support_event(evdev, EV_KEY);
+ evdev_support_event(evdev, EV_LED);
+ evdev_support_event(evdev, EV_REP);
+ evdev_support_all_known_keys(evdev);
+ evdev_support_led(evdev, LED_NUML);
+ evdev_support_led(evdev, LED_CAPSL);
+ evdev_support_led(evdev, LED_SCROLLL);
+
+ if (evdev_register(evdev))
+ evdev_free(evdev);
+ else
+ state->ks_evdev = evdev;
+ state->ks_evdev_state = 0;
+#endif
+
KBD_INIT_DONE(kbd);
}
@@ -532,6 +577,10 @@ kbdmux_term(keyboard_t *kbd)
kbd_unregister(kbd);
+#ifdef EVDEV_SUPPORT
+ evdev_free(state->ks_evdev);
+#endif
+
KBDMUX_LOCK_DESTROY(state);
bzero(state, sizeof(*state));
free(state, M_KBDMUX);
@@ -694,6 +743,20 @@ next_code:
kbd->kb_count ++;
+#ifdef EVDEV_SUPPORT
+ /* push evdev event */
+ if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) {
+ uint16_t key = evdev_scancode2key(&state->ks_evdev_state,
+ scancode);
+
+ if (key != KEY_RESERVED) {
+ evdev_push_event(state->ks_evdev, EV_KEY,
+ key, scancode & 0x80 ? 0 : 1);
+ evdev_sync(state->ks_evdev);
+ }
+ }
+#endif
+
/* return the byte as is for the K_RAW mode */
if (state->ks_mode == K_RAW) {
KBDMUX_UNLOCK(state);
@@ -1120,7 +1183,11 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
}
KBD_LED_VAL(kbd) = *(int *)arg;
-
+#ifdef EVDEV_SUPPORT
+ if (state->ks_evdev != NULL &&
+ evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
+ evdev_push_leds(state->ks_evdev, *(int *)arg);
+#endif
/* KDSETLED on all slave keyboards */
SLIST_FOREACH(k, &state->ks_kbds, next)
(void)kbdd_ioctl(k->kbd, KDSETLED, arg);
@@ -1197,7 +1264,11 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
kbd->kb_delay1 = delays[(mode >> 5) & 3];
kbd->kb_delay2 = rates[mode & 0x1f];
-
+#ifdef EVDEV_SUPPORT
+ if (state->ks_evdev != NULL &&
+ evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
+ evdev_push_repeats(state->ks_evdev, kbd);
+#endif
/* perform command on all slave keyboards */
SLIST_FOREACH(k, &state->ks_kbds, next)
(void)kbdd_ioctl(k->kbd, cmd, arg);
@@ -1396,4 +1467,6 @@ kbdmux_modevent(module_t mod, int type, void *data)
}
DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
-
+#ifdef EVDEV_SUPPORT
+MODULE_DEPEND(kbdmux, evdev, 1, 1, 1);
+#endif
diff --git a/sys/dev/rtwn/if_rtwn_tx.h b/sys/dev/rtwn/if_rtwn_tx.h
index d38a8550f2c4..e02fb56499d9 100644
--- a/sys/dev/rtwn/if_rtwn_tx.h
+++ b/sys/dev/rtwn/if_rtwn_tx.h
@@ -20,7 +20,9 @@
#define IF_RTWN_TX_H
void rtwn_drain_mbufq(struct rtwn_softc *);
+#ifdef IEEE80211_SUPPORT_SUPERG
void rtwn_ff_flush_all(struct rtwn_softc *, union sec_param *);
+#endif
int rtwn_transmit(struct ieee80211com *, struct mbuf *);
void rtwn_start(struct rtwn_softc *);
int rtwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
diff --git a/sys/dev/rtwn/pci/rtwn_pci_attach.c b/sys/dev/rtwn/pci/rtwn_pci_attach.c
index 00dcacc50f5a..e021c401ad3c 100644
--- a/sys/dev/rtwn/pci/rtwn_pci_attach.c
+++ b/sys/dev/rtwn/pci/rtwn_pci_attach.c
@@ -149,8 +149,8 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
/* Create RX buffer DMA tag. */
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
- 1, MCLBYTES, 0, NULL, NULL, &rx_ring->data_dmat);
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &rx_ring->data_dmat);
if (error != 0) {
device_printf(sc->sc_dev, "could not create rx buf DMA tag\n");
goto fail;
@@ -166,7 +166,8 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
goto fail;
}
- rx_data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ rx_data->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
+ MJUMPAGESIZE);
if (rx_data->m == NULL) {
device_printf(sc->sc_dev,
"could not allocate rx mbuf\n");
@@ -175,8 +176,8 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
}
error = bus_dmamap_load(rx_ring->data_dmat, rx_data->map,
- mtod(rx_data->m, void *), MCLBYTES, rtwn_pci_dma_map_addr,
- &rx_data->paddr, BUS_DMA_NOWAIT);
+ mtod(rx_data->m, void *), MJUMPAGESIZE,
+ rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->sc_dev,
"could not load rx buf DMA map");
@@ -184,7 +185,7 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
}
rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], rx_data->paddr,
- MCLBYTES, i);
+ MJUMPAGESIZE, i);
}
rx_ring->cur = 0;
@@ -206,7 +207,7 @@ rtwn_pci_reset_rx_list(struct rtwn_softc *sc)
for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
rx_data = &rx_ring->rx_data[i];
rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i],
- rx_data->paddr, MCLBYTES, i);
+ rx_data->paddr, MJUMPAGESIZE, i);
}
rx_ring->cur = 0;
}
@@ -287,8 +288,8 @@ rtwn_pci_alloc_tx_list(struct rtwn_softc *sc, int qid)
BUS_DMASYNC_PREWRITE);
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
- 1, MCLBYTES, 0, NULL, NULL, &tx_ring->data_dmat);
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &tx_ring->data_dmat);
if (error != 0) {
device_printf(sc->sc_dev, "could not create tx buf DMA tag\n");
goto fail;
diff --git a/sys/dev/rtwn/pci/rtwn_pci_rx.c b/sys/dev/rtwn/pci/rtwn_pci_rx.c
index df375a197605..00f7409efeb7 100644
--- a/sys/dev/rtwn/pci/rtwn_pci_rx.c
+++ b/sys/dev/rtwn/pci/rtwn_pci_rx.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_rx.h>
+#include <dev/rtwn/if_rtwn_task.h>
#include <dev/rtwn/if_rtwn_tx.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
@@ -120,7 +121,7 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN);
if (__predict_false(pktlen < sizeof(struct ieee80211_frame_ack) ||
- pktlen > MCLBYTES)) {
+ pktlen > MJUMPAGESIZE)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
"%s: frame is too short/long: %d\n", __func__, pktlen);
goto fail;
@@ -129,7 +130,7 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8;
shift = MS(rxdw0, R92C_RXDW0_SHIFT);
- m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ m1 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
if (__predict_false(m1 == NULL)) {
device_printf(sc->sc_dev, "%s: could not allocate RX mbuf\n",
__func__);
@@ -139,20 +140,20 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
bus_dmamap_unload(ring->data_dmat, rx_data->map);
error = bus_dmamap_load(ring->data_dmat, rx_data->map, mtod(m1, void *),
- MCLBYTES, rtwn_pci_dma_map_addr, &rx_data->paddr, 0);
+ MJUMPAGESIZE, rtwn_pci_dma_map_addr, &rx_data->paddr, 0);
if (error != 0) {
m_freem(m1);
error = bus_dmamap_load(ring->data_dmat, rx_data->map,
- mtod(rx_data->m, void *), MCLBYTES, rtwn_pci_dma_map_addr,
- &rx_data->paddr, BUS_DMA_NOWAIT);
+ mtod(rx_data->m, void *), MJUMPAGESIZE,
+ rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT);
if (error != 0)
panic("%s: could not load old RX mbuf",
device_get_name(sc->sc_dev));
/* Physical address may have changed. */
- rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MCLBYTES,
- desc_idx);
+ rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr,
+ MJUMPAGESIZE, desc_idx);
goto fail;
}
@@ -169,7 +170,7 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
__func__, pktlen, infosz, shift, rssi);
/* Update RX descriptor. */
- rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MCLBYTES,
+ rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MJUMPAGESIZE,
desc_idx);
/* Send the frame to the 802.11 layer. */
@@ -222,6 +223,8 @@ rtwn_pci_tx_done(struct rtwn_softc *sc, int qid)
data->ni = NULL;
ring->queued--;
+ KASSERT(ring->queued >= 0,
+ ("ring->queued (qid %d) underflow!\n", qid));
} else
m_freem(data->m);
@@ -235,9 +238,27 @@ rtwn_pci_tx_done(struct rtwn_softc *sc, int qid)
#endif
}
- if (ring->queued < (RTWN_PCI_TX_LIST_COUNT - 1))
+ if ((sc->qfullmsk & (1 << qid)) != 0 &&
+ ring->queued < (RTWN_PCI_TX_LIST_COUNT - 1)) {
sc->qfullmsk &= ~(1 << qid);
- rtwn_start(sc);
+ rtwn_start(sc);
+ }
+
+#ifdef IEEE80211_SUPPORT_SUPERG
+ /*
+ * If the TX active queue drops below a certain
+ * threshold, ensure we age fast-frames out so they're
+ * transmitted.
+ */
+ if (sc->sc_ratectl != RTWN_RATECTL_NET80211 && ring->queued <= 1) {
+ /*
+ * XXX TODO: just make this a callout timer schedule
+ * so we can flush the FF staging queue if we're
+ * approaching idle.
+ */
+ rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
+ }
+#endif
}
static void
@@ -261,6 +282,17 @@ rtwn_pci_rx_done(struct rtwn_softc *sc)
ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT;
}
+
+ /* Finished receive; age anything left on the FF queue by a little bump */
+ /*
+ * XXX TODO: just make this a callout timer schedule so we can
+ * flush the FF staging queue if we're approaching idle.
+ */
+#ifdef IEEE80211_SUPPORT_SUPERG
+ if (!(sc->sc_flags & RTWN_FW_LOADED) ||
+ sc->sc_ratectl != RTWN_RATECTL_NET80211)
+ rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
+#endif
}
void
diff --git a/sys/dev/rtwn/pci/rtwn_pci_tx.c b/sys/dev/rtwn/pci/rtwn_pci_tx.c
index d3e18083fdda..b450e4ee9f67 100644
--- a/sys/dev/rtwn/pci/rtwn_pci_tx.c
+++ b/sys/dev/rtwn/pci/rtwn_pci_tx.c
@@ -58,6 +58,37 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
+static struct mbuf *
+rtwn_mbuf_defrag(struct mbuf *m0, int how)
+{
+ struct mbuf *m = NULL;
+
+ KASSERT(m0->m_flags & M_PKTHDR,
+ ("M_PKTHDR flag is absent (m %p)!", m0));
+
+ /* NB: we need _exactly_ one mbuf (no less, no more). */
+ if (m0->m_pkthdr.len > MJUMPAGESIZE) {
+ /* XXX MJUM9BYTES? */
+ return (NULL);
+ } else if (m0->m_pkthdr.len > MCLBYTES) {
+ m = m_getjcl(how, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
+ if (m == NULL)
+ return (NULL);
+
+ if (m_dup_pkthdr(m, m0, how) == 0) {
+ m_freem(m);
+ return (NULL);
+ }
+
+ m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
+ m->m_len = m->m_pkthdr.len;
+ m_freem(m0);
+
+ return (m);
+ } else
+ return (m_defrag(m0, how));
+}
+
static int
rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m, uint8_t *tx_desc, uint8_t type)
@@ -114,7 +145,7 @@ rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni,
if (error != 0) {
struct mbuf *mnew;
- mnew = m_defrag(m, M_NOWAIT);
+ mnew = rtwn_mbuf_defrag(m, M_NOWAIT);
if (mnew == NULL) {
device_printf(sc->sc_dev, "can't defragment mbuf\n");
return (ENOBUFS);
diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
index 65e98a0399c9..f38782fced6d 100644
--- a/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
+++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
@@ -138,15 +138,11 @@ r92ce_adj_devcaps(struct rtwn_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
- /* XXX TODO: test everything that removed here before enabling. */
- /* XX do NOT enable PMGT until RSVD_PAGE command will not be fixed. */
- ic->ic_caps &= ~(
- IEEE80211_C_PMGT /* check null frame / device usability */
- | IEEE80211_C_SWAMSDUTX
- | IEEE80211_C_FF
- );
-
- ic->ic_htcaps = 0;
+ /*
+ * XXX do NOT enable PMGT until RSVD_PAGE command
+ * will not be tested / fixed + HRPWM register must be set too.
+ */
+ ic->ic_caps &= ~IEEE80211_C_PMGT;
}
void
diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c b/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c
index e6edea7af49d..c15d1e2a0340 100644
--- a/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c
+++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c
@@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/usb/rtwn_usb_var.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
-#include <dev/rtwn/rtl8192c/r92c_rom_defs.h>
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
#include <dev/rtwn/rtl8192c/usb/r92cu_priv.h>
diff --git a/sys/dev/rtwn/rtl8812a/r12a_rom.c b/sys/dev/rtwn/rtl8812a/r12a_rom.c
index df8bea64653f..f5d16a3ff718 100644
--- a/sys/dev/rtwn/rtl8812a/r12a_rom.c
+++ b/sys/dev/rtwn/rtl8812a/r12a_rom.c
@@ -65,7 +65,7 @@ r12a_parse_rom_common(struct rtwn_softc *sc, uint8_t *buf)
{
struct r12a_softc *rs = sc->sc_priv;
struct r12a_rom *rom = (struct r12a_rom *)buf;
- int i, j;
+ int i, j, k;
sc->thermal_meter = rom->thermal_meter;
rs->crystalcap = RTWN_GET_ROM_VAR(rom->crystalcap,
@@ -99,15 +99,15 @@ r12a_parse_rom_common(struct rtwn_softc *sc, uint8_t *buf)
MS(pwr_diff_2g->ht20_ofdm, HIGH_PART));
rs->bw40_tx_pwr_diff_2g[i][0] = 0;
- for (j = 1; j < nitems(pwr_diff_2g->diff123); j++) {
+ for (j = 1, k = 0; k < nitems(pwr_diff_2g->diff123); j++, k++) {
rs->cck_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8(
- MS(pwr_diff_2g->diff123[j].ofdm_cck, LOW_PART));
+ MS(pwr_diff_2g->diff123[k].ofdm_cck, LOW_PART));
rs->ofdm_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8(
- MS(pwr_diff_2g->diff123[j].ofdm_cck, HIGH_PART));
+ MS(pwr_diff_2g->diff123[k].ofdm_cck, HIGH_PART));
rs->bw20_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8(
- MS(pwr_diff_2g->diff123[j].ht40_ht20, LOW_PART));
+ MS(pwr_diff_2g->diff123[k].ht40_ht20, LOW_PART));
rs->bw40_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8(
- MS(pwr_diff_2g->diff123[j].ht40_ht20, HIGH_PART));
+ MS(pwr_diff_2g->diff123[k].ht40_ht20, HIGH_PART));
}
for (j = 0; j < R12A_GROUP_5G; j++) {
@@ -128,11 +128,12 @@ r12a_parse_rom_common(struct rtwn_softc *sc, uint8_t *buf)
rs->bw20_tx_pwr_diff_5g[i][0] = RTWN_SIGN4TO8(
MS(pwr_diff_5g->ht20_ofdm, HIGH_PART));
rs->bw40_tx_pwr_diff_5g[i][0] = 0;
- for (j = 1; j < nitems(pwr_diff_5g->ht40_ht20); j++) {
+ for (j = 1, k = 0; k < nitems(pwr_diff_5g->ht40_ht20);
+ j++, k++) {
rs->bw20_tx_pwr_diff_5g[i][j] = RTWN_SIGN4TO8(
- MS(pwr_diff_5g->ht40_ht20[j], LOW_PART));
+ MS(pwr_diff_5g->ht40_ht20[k], LOW_PART));
rs->bw40_tx_pwr_diff_5g[i][j] = RTWN_SIGN4TO8(
- MS(pwr_diff_5g->ht40_ht20[j], HIGH_PART));
+ MS(pwr_diff_5g->ht40_ht20[k], HIGH_PART));
}
for (j = 0; j < nitems(pwr_diff_5g->ht80_ht160); j++) {
diff --git a/sys/dev/rtwn/rtl8812a/r12a_var.h b/sys/dev/rtwn/rtl8812a/r12a_var.h
index 9c22cf98ddb7..e236a5cdeec4 100644
--- a/sys/dev/rtwn/rtl8812a/r12a_var.h
+++ b/sys/dev/rtwn/rtl8812a/r12a_var.h
@@ -64,16 +64,16 @@ struct r12a_softc {
uint8_t ht40_tx_pwr_2g[R12A_MAX_RF_PATH][R12A_GROUP_2G];
uint8_t ht40_tx_pwr_5g[R12A_MAX_RF_PATH][R12A_GROUP_5G];
- uint8_t cck_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
- uint8_t ofdm_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
- uint8_t bw20_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
- uint8_t bw40_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
+ int8_t cck_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
+ int8_t ofdm_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
+ int8_t bw20_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
+ int8_t bw40_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
- uint8_t ofdm_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
- uint8_t bw20_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
- uint8_t bw40_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
- uint8_t bw80_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
- uint8_t bw160_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
+ int8_t ofdm_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
+ int8_t bw20_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
+ int8_t bw40_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
+ int8_t bw80_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
+ int8_t bw160_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT];
int sc_ant;
diff --git a/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c b/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c
index 9134dce51afb..855d2b0b7c80 100644
--- a/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c
+++ b/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c
@@ -68,7 +68,6 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/rtl8812a/r12a_priv.h>
#include <dev/rtwn/rtl8812a/r12a_reg.h>
#include <dev/rtwn/rtl8812a/r12a_var.h>
-#include <dev/rtwn/rtl8812a/r12a_rom_defs.h>
#include <dev/rtwn/rtl8812a/usb/r12au.h>
#include <dev/rtwn/rtl8812a/usb/r12au_tx_desc.h>
diff --git a/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c b/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c
index a9bc47b8969b..86f605c335dc 100644
--- a/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c
+++ b/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c
@@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8812a/r12a_var.h>
-#include <dev/rtwn/rtl8812a/r12a_rom_defs.h>
#include <dev/rtwn/rtl8812a/usb/r12au.h>
#include <dev/rtwn/rtl8812a/usb/r12au_tx_desc.h>
diff --git a/sys/dev/rtwn/usb/rtwn_usb_rx.c b/sys/dev/rtwn/usb/rtwn_usb_rx.c
index 8c6aa1686794..f15d6c662525 100644
--- a/sys/dev/rtwn/usb/rtwn_usb_rx.c
+++ b/sys/dev/rtwn/usb/rtwn_usb_rx.c
@@ -326,7 +326,8 @@ finish:
* flush the FF staging queue if we're approaching idle.
*/
#ifdef IEEE80211_SUPPORT_SUPERG
- if (!(sc->sc_flags & RTWN_FW_LOADED))
+ if (!(sc->sc_flags & RTWN_FW_LOADED) ||
+ sc->sc_ratectl != RTWN_RATECTL_NET80211)
rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
#endif
diff --git a/sys/dev/smbus/smb.c b/sys/dev/smbus/smb.c
index 21d1e2f7c3d3..5f6eff039628 100644
--- a/sys/dev/smbus/smb.c
+++ b/sys/dev/smbus/smb.c
@@ -41,7 +41,9 @@
#include "smbus_if.h"
-#define BUFSIZE 1024
+#define SMB_OLD_READB _IOW('i', 7, struct smbcmd)
+#define SMB_OLD_READW _IOW('i', 8, struct smbcmd)
+#define SMB_OLD_PCALL _IOW('i', 9, struct smbcmd)
struct smb_softc {
device_t sc_dev;
@@ -224,7 +226,9 @@ smbioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t
s->cmd, s->wdata.word));
break;
+ case SMB_OLD_READB:
case SMB_READB:
+ /* NB: for SMB_OLD_READB the read data goes to rbuf only. */
error = smbus_error(smbus_readb(parent, s->slave, s->cmd,
&s->rdata.byte));
if (error)
@@ -235,7 +239,9 @@ smbioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t
}
break;
+ case SMB_OLD_READW:
case SMB_READW:
+ /* NB: for SMB_OLD_READW the read data goes to rbuf only. */
error = smbus_error(smbus_readw(parent, s->slave, s->cmd,
&s->rdata.word));
if (error)
@@ -248,7 +254,9 @@ smbioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t
}
break;
+ case SMB_OLD_PCALL:
case SMB_PCALL:
+ /* NB: for SMB_OLD_PCALL the read data goes to rbuf only. */
error = smbus_error(smbus_pcall(parent, s->slave, s->cmd,
s->wdata.word, &s->rdata.word));
if (error)
diff --git a/sys/dev/smbus/smb.h b/sys/dev/smbus/smb.h
index 44b71e8a40ef..b766a656d277 100644
--- a/sys/dev/smbus/smb.h
+++ b/sys/dev/smbus/smb.h
@@ -63,11 +63,10 @@ struct smbcmd {
#define SMB_RECVB _IOWR('i', 4, struct smbcmd)
#define SMB_WRITEB _IOW('i', 5, struct smbcmd)
#define SMB_WRITEW _IOW('i', 6, struct smbcmd)
-#define SMB_READB _IOW('i', 7, struct smbcmd)
-#define SMB_READW _IOW('i', 8, struct smbcmd)
-#define SMB_PCALL _IOW('i', 9, struct smbcmd)
+#define SMB_READB _IOWR('i', 7, struct smbcmd)
+#define SMB_READW _IOWR('i', 8, struct smbcmd)
+#define SMB_PCALL _IOWR('i', 9, struct smbcmd)
#define SMB_BWRITE _IOW('i', 10, struct smbcmd)
-#define SMB_OLD_BREAD _IOW('i', 11, struct smbcmd)
#define SMB_BREAD _IOWR('i', 11, struct smbcmd)
#define SMB_OLD_TRANS _IOWR('i', 12, struct smbcmd)
diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c
index adcf5d2bfa02..8ad3714e2f61 100644
--- a/sys/dev/uart/uart_bus_fdt.c
+++ b/sys/dev/uart/uart_bus_fdt.c
@@ -123,7 +123,7 @@ uart_fdt_find_compatible(phandle_t node, const struct ofw_compat_data *cd)
const struct ofw_compat_data *ocd;
for (ocd = cd; ocd->ocd_str != NULL; ocd++) {
- if (fdt_is_compatible(node, ocd->ocd_str))
+ if (ofw_bus_node_is_compatible(node, ocd->ocd_str))
return (ocd);
}
return (NULL);
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index f4dbcfc2dcc7..6c9d7aa23a06 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -573,7 +573,7 @@ uart_bus_attach(device_t dev)
* the device.
*/
sc0 = device_get_softc(dev);
- if (sc0->sc_class->size > sizeof(*sc)) {
+ if (sc0->sc_class->size > device_get_driver(dev)->size) {
sc = malloc(sc0->sc_class->size, M_UART, M_WAITOK|M_ZERO);
bcopy(sc0, sc, sizeof(*sc));
device_set_softc(dev, sc);
@@ -781,11 +781,10 @@ uart_bus_detach(device_t dev)
mtx_destroy(&sc->sc_hwmtx_s);
- if (sc->sc_class->size > sizeof(*sc)) {
+ if (sc->sc_class->size > device_get_driver(dev)->size) {
device_set_softc(dev, NULL);
free(sc, M_UART);
- } else
- device_set_softc(dev, NULL);
+ }
return (0);
}
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 2498fa37db76..74d7bb7c1f95 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -198,6 +198,9 @@ ns8250_flush(struct uart_bas *bas, int what)
uint8_t fcr;
fcr = FCR_ENABLE;
+#ifdef CPU_XBURST
+ fcr |= FCR_UART_ON;
+#endif
if (what & UART_FLUSH_TRANSMITTER)
fcr |= FCR_XMT_RST;
if (what & UART_FLUSH_RECEIVER)
@@ -268,6 +271,10 @@ ns8250_probe(struct uart_bas *bas)
{
u_char val;
+#ifdef CPU_XBURST
+ uart_setreg(bas, REG_FCR, FCR_UART_ON);
+#endif
+
/* Check known 0 bits that don't depend on DLAB. */
val = uart_getreg(bas, REG_IIR);
if (val & 0x30)
@@ -289,7 +296,7 @@ static void
ns8250_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
int parity)
{
- u_char ier;
+ u_char ier, val;
if (bas->rclk == 0)
bas->rclk = DEFAULT_RCLK;
@@ -306,7 +313,11 @@ ns8250_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
uart_barrier(bas);
/* Disable the FIFO (if present). */
- uart_setreg(bas, REG_FCR, 0);
+ val = 0;
+#ifdef CPU_XBURST
+ val = FCR_UART_ON;
+#endif
+ uart_setreg(bas, REG_FCR, val);
uart_barrier(bas);
/* Set RTS & DTR. */
@@ -461,6 +472,9 @@ ns8250_bus_attach(struct uart_softc *sc)
ns8250->mcr = uart_getreg(bas, REG_MCR);
ns8250->fcr = FCR_ENABLE;
+#ifdef CPU_XBURST
+ ns8250->fcr |= FCR_UART_ON;
+#endif
if (!resource_int_value("uart", device_get_unit(sc->sc_dev), "flags",
&ivar)) {
if (UART_FLAGS_FCR_RX_LOW(ivar))
@@ -753,6 +767,7 @@ ns8250_bus_probe(struct uart_softc *sc)
struct uart_bas *bas;
int count, delay, error, limit;
uint8_t lsr, mcr, ier;
+ uint8_t val;
ns8250 = (struct ns8250_softc *)sc;
bas = &sc->sc_bas;
@@ -786,7 +801,11 @@ ns8250_bus_probe(struct uart_softc *sc)
* done. Since this is the first time we enable the FIFOs, we reset
* them.
*/
- uart_setreg(bas, REG_FCR, FCR_ENABLE);
+ val = FCR_ENABLE;
+#ifdef CPU_XBURST
+ val |= FCR_UART_ON;
+#endif
+ uart_setreg(bas, REG_FCR, val);
uart_barrier(bas);
if (!(uart_getreg(bas, REG_IIR) & IIR_FIFO_MASK)) {
/*
@@ -800,7 +819,11 @@ ns8250_bus_probe(struct uart_softc *sc)
return (0);
}
- uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST);
+ val = FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST;
+#ifdef CPU_XBURST
+ val |= FCR_UART_ON;
+#endif
+ uart_setreg(bas, REG_FCR, val);
uart_barrier(bas);
count = 0;
@@ -810,7 +833,11 @@ ns8250_bus_probe(struct uart_softc *sc)
error = ns8250_drain(bas, UART_DRAIN_RECEIVER|UART_DRAIN_TRANSMITTER);
if (error) {
uart_setreg(bas, REG_MCR, mcr);
- uart_setreg(bas, REG_FCR, 0);
+ val = 0;
+#ifdef CPU_XBURST
+ val |= FCR_UART_ON;
+#endif
+ uart_setreg(bas, REG_FCR, val);
uart_barrier(bas);
goto describe;
}
@@ -840,7 +867,11 @@ ns8250_bus_probe(struct uart_softc *sc)
ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask;
uart_setreg(bas, REG_IER, ier);
uart_setreg(bas, REG_MCR, mcr);
- uart_setreg(bas, REG_FCR, 0);
+ val = 0;
+#ifdef CPU_XBURST
+ val |= FCR_UART_ON;
+#endif
+ uart_setreg(bas, REG_FCR, val);
uart_barrier(bas);
count = 0;
goto describe;
diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c
index 5560f070dc96..08c037706eac 100644
--- a/sys/dev/usb/controller/dwc_otg.c
+++ b/sys/dev/usb/controller/dwc_otg.c
@@ -98,10 +98,6 @@
GINTSTS_WKUPINT | GINTSTS_USBSUSP | GINTMSK_OTGINTMSK | \
GINTSTS_SESSREQINT)
-#define DWC_OTG_PHY_ULPI 0
-#define DWC_OTG_PHY_HSIC 1
-#define DWC_OTG_PHY_INTERNAL 2
-
#ifndef DWC_OTG_PHY_DEFAULT
#define DWC_OTG_PHY_DEFAULT DWC_OTG_PHY_ULPI
#endif
@@ -110,10 +106,10 @@ static int dwc_otg_phy_type = DWC_OTG_PHY_DEFAULT;
static SYSCTL_NODE(_hw_usb, OID_AUTO, dwc_otg, CTLFLAG_RW, 0, "USB DWC OTG");
SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, phy_type, CTLFLAG_RDTUN,
- &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2 - ULPI/HSIC/INTERNAL");
+ &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2/3 - ULPI/HSIC/INTERNAL/UTMI+");
#ifdef USB_DEBUG
-static int dwc_otg_debug;
+static int dwc_otg_debug = 0;
SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, debug, CTLFLAG_RWTUN,
&dwc_otg_debug, 0, "DWC OTG debug level");
@@ -3889,8 +3885,13 @@ dwc_otg_init(struct dwc_otg_softc *sc)
break;
}
- /* select HSIC, ULPI or internal PHY mode */
- switch (dwc_otg_phy_type) {
+ if (sc->sc_phy_type == 0)
+ sc->sc_phy_type = dwc_otg_phy_type + 1;
+ if (sc->sc_phy_bits == 0)
+ sc->sc_phy_bits = 16;
+
+ /* select HSIC, ULPI, UTMI+ or internal PHY mode */
+ switch (sc->sc_phy_type) {
case DWC_OTG_PHY_HSIC:
DWC_OTG_WRITE_4(sc, DOTG_GUSBCFG,
GUSBCFG_PHYIF |
@@ -3914,6 +3915,16 @@ dwc_otg_init(struct dwc_otg_softc *sc)
DWC_OTG_WRITE_4(sc, DOTG_GLPMCFG,
temp & ~GLPMCFG_HSIC_CONN);
break;
+ case DWC_OTG_PHY_UTMI:
+ DWC_OTG_WRITE_4(sc, DOTG_GUSBCFG,
+ (sc->sc_phy_bits == 16 ? GUSBCFG_PHYIF : 0) |
+ GUSBCFG_TRD_TIM_SET(5) | temp);
+ DWC_OTG_WRITE_4(sc, DOTG_GOTGCTL, 0);
+
+ temp = DWC_OTG_READ_4(sc, DOTG_GLPMCFG);
+ DWC_OTG_WRITE_4(sc, DOTG_GLPMCFG,
+ temp & ~GLPMCFG_HSIC_CONN);
+ break;
case DWC_OTG_PHY_INTERNAL:
DWC_OTG_WRITE_4(sc, DOTG_GUSBCFG,
GUSBCFG_PHYSEL |
diff --git a/sys/dev/usb/controller/dwc_otg.h b/sys/dev/usb/controller/dwc_otg.h
index 038b072aeef7..7f5ede481e58 100644
--- a/sys/dev/usb/controller/dwc_otg.h
+++ b/sys/dev/usb/controller/dwc_otg.h
@@ -191,6 +191,13 @@ struct dwc_otg_softc {
uint16_t sc_active_rx_ep;
uint16_t sc_last_frame_num;
+ uint8_t sc_phy_type;
+ uint8_t sc_phy_bits;
+#define DWC_OTG_PHY_ULPI 1
+#define DWC_OTG_PHY_HSIC 2
+#define DWC_OTG_PHY_INTERNAL 3
+#define DWC_OTG_PHY_UTMI 4
+
uint8_t sc_timer_active;
uint8_t sc_dev_ep_max;
uint8_t sc_dev_in_ep_max;
diff --git a/sys/dev/usb/controller/dwc_otg_fdt.c b/sys/dev/usb/controller/dwc_otg_fdt.c
index 80d3388050ff..8cc8e754fabb 100644
--- a/sys/dev/usb/controller/dwc_otg_fdt.c
+++ b/sys/dev/usb/controller/dwc_otg_fdt.c
@@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/controller/dwc_otg_fdt.h>
static device_probe_t dwc_otg_probe;
-static device_detach_t dwc_otg_detach;
static int
dwc_otg_probe(device_t dev)
@@ -159,7 +158,7 @@ error:
return (ENXIO);
}
-static int
+int
dwc_otg_detach(device_t dev)
{
struct dwc_otg_fdt_softc *sc = device_get_softc(dev);
diff --git a/sys/dev/usb/controller/dwc_otg_fdt.h b/sys/dev/usb/controller/dwc_otg_fdt.h
index 9e01118c80d6..634b7960b0a3 100644
--- a/sys/dev/usb/controller/dwc_otg_fdt.h
+++ b/sys/dev/usb/controller/dwc_otg_fdt.h
@@ -35,5 +35,6 @@ struct dwc_otg_fdt_softc {
extern driver_t dwc_otg_driver;
device_attach_t dwc_otg_attach;
+device_attach_t dwc_otg_detach;
#endif
diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c
index 915dd838b380..375ab5f21894 100644
--- a/sys/dev/usb/net/if_smsc.c
+++ b/sys/dev/usb/net/if_smsc.c
@@ -152,7 +152,7 @@ static const struct usb_device_id smsc_devs[] = {
device_printf((sc)->sc_ue.ue_dev, "debug: " fmt, ##args); \
} while(0)
#else
-#define smsc_dbg_printf(sc, fmt, args...)
+#define smsc_dbg_printf(sc, fmt, args...) do { } while (0)
#endif
#define smsc_warn_printf(sc, fmt, args...) \
@@ -822,7 +822,6 @@ static int smsc_sethwcsum(struct smsc_softc *sc)
return (0);
}
-
/**
* smsc_setmacaddress - Sets the mac address in the device
* @sc: driver soft context
@@ -905,6 +904,9 @@ smsc_init(struct usb_ether *ue)
SMSC_LOCK_ASSERT(sc, MA_OWNED);
+ if (smsc_setmacaddress(sc, IF_LLADDR(ifp)))
+ smsc_dbg_printf(sc, "setting MAC address failed\n");
+
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
return;
@@ -1566,8 +1568,8 @@ smsc_fdt_find_eth_node(phandle_t start)
/* Traverse through entire tree to find usb ethernet nodes. */
for (node = OF_child(start); node != 0; node = OF_peer(node)) {
- if (fdt_is_compatible(node, "net,ethernet") &&
- fdt_is_compatible(node, "usb,device"))
+ if (ofw_bus_node_is_compatible(node, "net,ethernet") &&
+ ofw_bus_node_is_compatible(node, "usb,device"))
return (node);
child = smsc_fdt_find_eth_node(node);
if (child != -1)
diff --git a/sys/dev/virtio/console/virtio_console.c b/sys/dev/virtio/console/virtio_console.c
index bfef07f1d94a..4c673c8d1293 100644
--- a/sys/dev/virtio/console/virtio_console.c
+++ b/sys/dev/virtio/console/virtio_console.c
@@ -600,7 +600,7 @@ vtcon_ctrl_event_enqueue(struct vtcon_softc *sc,
sglist_init(&sg, 2, segs);
error = sglist_append(&sg, control,
- sizeof(struct virtio_console_control));
+ sizeof(struct virtio_console_control) + VTCON_BULK_BUFSZ);
KASSERT(error == 0, ("%s: error %d adding control to sglist",
__func__, error));
@@ -633,7 +633,8 @@ vtcon_ctrl_event_requeue(struct vtcon_softc *sc,
{
int error;
- bzero(control, sizeof(struct virtio_console_control));
+ bzero(control, sizeof(struct virtio_console_control) +
+ VTCON_BULK_BUFSZ);
error = vtcon_ctrl_event_enqueue(sc, control);
KASSERT(error == 0,
diff --git a/sys/fs/autofs/autofs.c b/sys/fs/autofs/autofs.c
index 5389b1c4b168..1119ee7a4b1b 100644
--- a/sys/fs/autofs/autofs.c
+++ b/sys/fs/autofs/autofs.c
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 02b85e7e7333..7b65a6061295 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -827,6 +827,12 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
struct dqblk dqb;
uid_t savuid;
#endif
+ static struct timeval last64fileid;
+ static size_t count64fileid;
+ static struct timeval last64mountfileid;
+ static size_t count64mountfileid;
+ static struct timeval warninterval = { 60, 0 };
+
if (compare) {
retnotsup = 0;
error = nfsrv_getattrbits(nd, &attrbits, NULL, &retnotsup);
@@ -1202,8 +1208,14 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
*retcmpp = NFSERR_NOTSAME;
}
} else if (nap != NULL) {
- if (*tl++)
- printf("NFSv4 fileid > 32bits\n");
+ if (*tl++) {
+ count64fileid++;
+ if (ratecheck(&last64fileid, &warninterval)) {
+ printf("NFSv4 fileid > 32bits (%zu occurrences)\n",
+ count64fileid);
+ count64fileid = 0;
+ }
+ }
nap->na_fileid = thyp;
}
attrsum += NFSX_HYPER;
@@ -1740,8 +1752,14 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
}
}
} else if (nap != NULL) {
- if (*tl++)
- printf("NFSv4 mounted on fileid > 32bits\n");
+ if (*tl++) {
+ count64mountfileid++;
+ if (ratecheck(&last64mountfileid, &warninterval)) {
+ printf("NFSv4 mounted on fileid > 32bits (%zu occurrences)\n",
+ count64mountfileid);
+ count64mountfileid = 0;
+ }
+ }
nap->na_mntonfileno = thyp;
}
attrsum += NFSX_HYPER;
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index 7ce4789c72ab..d3019f605491 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -1372,12 +1372,9 @@ retry:
VM_WAIT;
VM_OBJECT_WLOCK(uobj);
goto retry;
- } else if (m->valid != VM_PAGE_BITS_ALL)
- rv = vm_pager_get_pages(uobj, &m, 1,
- NULL, NULL);
- else
- /* A cached page was reactivated. */
- rv = VM_PAGER_OK;
+ }
+ rv = vm_pager_get_pages(uobj, &m, 1, NULL,
+ NULL);
vm_page_lock(m);
if (rv == VM_PAGER_OK) {
vm_page_deactivate(m);
diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c
index 52c007efd1d9..e1daae1ddaf1 100644
--- a/sys/geom/mirror/g_mirror.c
+++ b/sys/geom/mirror/g_mirror.c
@@ -79,12 +79,12 @@ SYSCTL_UINT(_kern_geom_mirror, OID_AUTO, sync_requests, CTLFLAG_RDTUN,
static eventhandler_tag g_mirror_post_sync = NULL;
static int g_mirror_shutdown = 0;
-static int g_mirror_destroy_geom(struct gctl_req *req, struct g_class *mp,
- struct g_geom *gp);
+static g_ctl_destroy_geom_t g_mirror_destroy_geom;
static g_taste_t g_mirror_taste;
+static g_init_t g_mirror_init;
+static g_fini_t g_mirror_fini;
+static g_provgone_t g_mirror_providergone;
static g_resize_t g_mirror_resize;
-static void g_mirror_init(struct g_class *mp);
-static void g_mirror_fini(struct g_class *mp);
struct g_class g_mirror_class = {
.name = G_MIRROR_CLASS_NAME,
@@ -94,6 +94,7 @@ struct g_class g_mirror_class = {
.destroy_geom = g_mirror_destroy_geom,
.init = g_mirror_init,
.fini = g_mirror_fini,
+ .providergone = g_mirror_providergone,
.resize = g_mirror_resize
};
@@ -508,6 +509,26 @@ g_mirror_destroy_disk(struct g_mirror_disk *disk)
}
static void
+g_mirror_free_device(struct g_mirror_softc *sc)
+{
+
+ mtx_destroy(&sc->sc_queue_mtx);
+ mtx_destroy(&sc->sc_events_mtx);
+ mtx_destroy(&sc->sc_done_mtx);
+ sx_destroy(&sc->sc_lock);
+ free(sc, M_MIRROR);
+}
+
+static void
+g_mirror_providergone(struct g_provider *pp)
+{
+ struct g_mirror_softc *sc = pp->private;
+
+ if ((--sc->sc_refcnt) == 0)
+ g_mirror_free_device(sc);
+}
+
+static void
g_mirror_destroy_device(struct g_mirror_softc *sc)
{
struct g_mirror_disk *disk;
@@ -549,12 +570,10 @@ g_mirror_destroy_device(struct g_mirror_softc *sc)
g_wither_geom(sc->sc_sync.ds_geom, ENXIO);
G_MIRROR_DEBUG(0, "Device %s destroyed.", gp->name);
g_wither_geom(gp, ENXIO);
- g_topology_unlock();
- mtx_destroy(&sc->sc_queue_mtx);
- mtx_destroy(&sc->sc_events_mtx);
- mtx_destroy(&sc->sc_done_mtx);
sx_xunlock(&sc->sc_lock);
- sx_destroy(&sc->sc_lock);
+ if ((--sc->sc_refcnt) == 0)
+ g_mirror_free_device(sc);
+ g_topology_unlock();
}
static void
@@ -868,7 +887,7 @@ g_mirror_flush_done(struct bio *bp)
struct bio *pbp;
pbp = bp->bio_parent;
- sc = pbp->bio_to->geom->softc;
+ sc = pbp->bio_to->private;
mtx_lock(&sc->sc_done_mtx);
if (pbp->bio_error == 0)
pbp->bio_error = bp->bio_error;
@@ -905,7 +924,7 @@ g_mirror_regular_request(struct bio *bp)
g_topology_assert_not();
pbp = bp->bio_parent;
- sc = pbp->bio_to->geom->softc;
+ sc = pbp->bio_to->private;
bp->bio_from->index--;
if (bp->bio_cmd == BIO_WRITE)
sc->sc_writes--;
@@ -1036,7 +1055,7 @@ g_mirror_candelete(struct bio *bp)
struct g_mirror_disk *disk;
int *val;
- sc = bp->bio_to->geom->softc;
+ sc = bp->bio_to->private;
LIST_FOREACH(disk, &sc->sc_disks, d_next) {
if (disk->d_flags & G_MIRROR_DISK_FLAG_CANDELETE)
break;
@@ -1061,7 +1080,7 @@ g_mirror_kernel_dump(struct bio *bp)
* we will not be able to read the dump after the reboot if it will be
* connected and synchronized later. Can we do something better?
*/
- sc = bp->bio_to->geom->softc;
+ sc = bp->bio_to->private;
disk = LIST_FIRST(&sc->sc_disks);
gkd = (struct g_kerneldump *)bp->bio_data;
@@ -1121,7 +1140,7 @@ g_mirror_start(struct bio *bp)
{
struct g_mirror_softc *sc;
- sc = bp->bio_to->geom->softc;
+ sc = bp->bio_to->private;
/*
* If sc == NULL or there are no valid disks, provider's error
* should be set and g_mirror_start() should not be called at all.
@@ -1637,7 +1656,7 @@ g_mirror_register_request(struct bio *bp)
{
struct g_mirror_softc *sc;
- sc = bp->bio_to->geom->softc;
+ sc = bp->bio_to->private;
switch (bp->bio_cmd) {
case BIO_READ:
switch (sc->sc_balance) {
@@ -1804,7 +1823,6 @@ g_mirror_try_destroy(struct g_mirror_softc *sc)
} else {
g_topology_unlock();
g_mirror_destroy_device(sc);
- free(sc, M_MIRROR);
}
return (1);
}
@@ -2117,6 +2135,8 @@ g_mirror_launch_provider(struct g_mirror_softc *sc)
}
}
}
+ pp->private = sc;
+ sc->sc_refcnt++;
sc->sc_provider = pp;
g_error_provider(pp, 0);
g_topology_unlock();
@@ -2898,9 +2918,7 @@ g_mirror_access(struct g_provider *pp, int acr, int acw, int ace)
G_MIRROR_DEBUG(2, "Access request for %s: r%dw%de%d.", pp->name, acr,
acw, ace);
- sc = pp->geom->softc;
- if (sc == NULL && acr <= 0 && acw <= 0 && ace <= 0)
- return (0);
+ sc = pp->private;
KASSERT(sc != NULL, ("NULL softc (provider=%s).", pp->name));
g_topology_unlock();
@@ -2959,6 +2977,7 @@ g_mirror_create(struct g_class *mp, const struct g_mirror_metadata *md)
sc->sc_idle = 1;
sc->sc_last_write = time_uptime;
sc->sc_writes = 0;
+ sc->sc_refcnt = 1;
sx_init(&sc->sc_lock, "gmirror:lock");
bioq_init(&sc->sc_queue);
mtx_init(&sc->sc_queue_mtx, "gmirror:queue", NULL, MTX_DEF);
@@ -2989,12 +3008,8 @@ g_mirror_create(struct g_class *mp, const struct g_mirror_metadata *md)
G_MIRROR_DEBUG(1, "Cannot create kernel thread for %s.",
sc->sc_name);
g_destroy_geom(sc->sc_sync.ds_geom);
- mtx_destroy(&sc->sc_done_mtx);
- mtx_destroy(&sc->sc_events_mtx);
- mtx_destroy(&sc->sc_queue_mtx);
- sx_destroy(&sc->sc_lock);
g_destroy_geom(sc->sc_geom);
- free(sc, M_MIRROR);
+ g_mirror_free_device(sc);
return (NULL);
}
@@ -3017,8 +3032,6 @@ g_mirror_destroy(struct g_mirror_softc *sc, int how)
struct g_mirror_disk *disk;
g_topology_assert_not();
- if (sc == NULL)
- return (ENXIO);
sx_assert(&sc->sc_lock, SX_XLOCKED);
if (sc->sc_provider_open != 0 || SCHEDULER_STOPPED()) {
@@ -3068,7 +3081,6 @@ g_mirror_destroy(struct g_mirror_softc *sc, int how)
G_MIRROR_DEBUG(4, "%s: Woken up %p.", __func__, &sc->sc_worker);
sx_xlock(&sc->sc_lock);
g_mirror_destroy_device(sc);
- free(sc, M_MIRROR);
return (0);
}
diff --git a/sys/geom/mirror/g_mirror.h b/sys/geom/mirror/g_mirror.h
index e730e42e8766..ed499a55c8f3 100644
--- a/sys/geom/mirror/g_mirror.h
+++ b/sys/geom/mirror/g_mirror.h
@@ -207,6 +207,7 @@ struct g_mirror_softc {
int sc_idle; /* DIRTY flags removed. */
time_t sc_last_write;
u_int sc_writes;
+ u_int sc_refcnt; /* Number of softc references */
TAILQ_HEAD(, g_mirror_event) sc_events;
struct mtx sc_events_mtx;
diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c
index 6644532d02e7..b461747bf356 100644
--- a/sys/geom/multipath/g_multipath.c
+++ b/sys/geom/multipath/g_multipath.c
@@ -470,7 +470,7 @@ g_multipath_access(struct g_provider *pp, int dr, int dw, int de)
gp = pp->geom;
/* Error used if we have no valid consumers. */
- error = ENXIO;
+ error = (dr > 0 || dw > 0 || de > 0) ? ENXIO : 0;
LIST_FOREACH(cp, &gp->consumer, consumer) {
if (cp->index & MP_WITHER)
diff --git a/sys/gnu/dts/include/dt-bindings/dma/jz4780-dma.h b/sys/gnu/dts/include/dt-bindings/dma/jz4780-dma.h
new file mode 100644
index 000000000000..df017fdfb44e
--- /dev/null
+++ b/sys/gnu/dts/include/dt-bindings/dma/jz4780-dma.h
@@ -0,0 +1,49 @@
+#ifndef __DT_BINDINGS_DMA_JZ4780_DMA_H__
+#define __DT_BINDINGS_DMA_JZ4780_DMA_H__
+
+/*
+ * Request type numbers for the JZ4780 DMA controller (written to the DRTn
+ * register for the channel).
+ */
+#define JZ4780_DMA_I2S1_TX 0x4
+#define JZ4780_DMA_I2S1_RX 0x5
+#define JZ4780_DMA_I2S0_TX 0x6
+#define JZ4780_DMA_I2S0_RX 0x7
+#define JZ4780_DMA_AUTO 0x8
+#define JZ4780_DMA_SADC_RX 0x9
+#define JZ4780_DMA_UART4_TX 0xc
+#define JZ4780_DMA_UART4_RX 0xd
+#define JZ4780_DMA_UART3_TX 0xe
+#define JZ4780_DMA_UART3_RX 0xf
+#define JZ4780_DMA_UART2_TX 0x10
+#define JZ4780_DMA_UART2_RX 0x11
+#define JZ4780_DMA_UART1_TX 0x12
+#define JZ4780_DMA_UART1_RX 0x13
+#define JZ4780_DMA_UART0_TX 0x14
+#define JZ4780_DMA_UART0_RX 0x15
+#define JZ4780_DMA_SSI0_TX 0x16
+#define JZ4780_DMA_SSI0_RX 0x17
+#define JZ4780_DMA_SSI1_TX 0x18
+#define JZ4780_DMA_SSI1_RX 0x19
+#define JZ4780_DMA_MSC0_TX 0x1a
+#define JZ4780_DMA_MSC0_RX 0x1b
+#define JZ4780_DMA_MSC1_TX 0x1c
+#define JZ4780_DMA_MSC1_RX 0x1d
+#define JZ4780_DMA_MSC2_TX 0x1e
+#define JZ4780_DMA_MSC2_RX 0x1f
+#define JZ4780_DMA_PCM0_TX 0x20
+#define JZ4780_DMA_PCM0_RX 0x21
+#define JZ4780_DMA_SMB0_TX 0x24
+#define JZ4780_DMA_SMB0_RX 0x25
+#define JZ4780_DMA_SMB1_TX 0x26
+#define JZ4780_DMA_SMB1_RX 0x27
+#define JZ4780_DMA_SMB2_TX 0x28
+#define JZ4780_DMA_SMB2_RX 0x29
+#define JZ4780_DMA_SMB3_TX 0x2a
+#define JZ4780_DMA_SMB3_RX 0x2b
+#define JZ4780_DMA_SMB4_TX 0x2c
+#define JZ4780_DMA_SMB4_RX 0x2d
+#define JZ4780_DMA_DES_TX 0x2e
+#define JZ4780_DMA_DES_RX 0x2f
+
+#endif /* __DT_BINDINGS_DMA_JZ4780_DMA_H__ */
diff --git a/sys/gnu/dts/include/dt-bindings/net/rfkill-regulator.h b/sys/gnu/dts/include/dt-bindings/net/rfkill-regulator.h
new file mode 100644
index 000000000000..ae32273c7ba3
--- /dev/null
+++ b/sys/gnu/dts/include/dt-bindings/net/rfkill-regulator.h
@@ -0,0 +1,23 @@
+/*
+ * This header provides macros for rfkill-regulator bindings.
+ *
+ * Copyright (C) 2014 Marek Belisko <marek@goldelico.com>
+ *
+ * GPLv2 only
+ */
+
+#ifndef __DT_BINDINGS_RFKILL_REGULATOR_H__
+#define __DT_BINDINGS_RFKILL_REGULATOR_H__
+
+
+#define RFKILL_TYPE_ALL (0)
+#define RFKILL_TYPE_WLAN (1)
+#define RFKILL_TYPE_BLUETOOTH (2)
+#define RFKILL_TYPE_UWB (3)
+#define RFKILL_TYPE_WIMAX (4)
+#define RFKILL_TYPE_WWAN (5)
+#define RFKILL_TYPE_GPS (6)
+#define RFKILL_TYPE_FM (7)
+#define RFKILL_TYPE_NFC (8)
+
+#endif /* __DT_BINDINGS_RFKILL_REGULATOR_H__ */
diff --git a/sys/gnu/dts/mips/ingenic/canna.dts b/sys/gnu/dts/mips/ingenic/canna.dts
new file mode 100644
index 000000000000..98ddb98f7ee0
--- /dev/null
+++ b/sys/gnu/dts/mips/ingenic/canna.dts
@@ -0,0 +1,42 @@
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/rfkill-regulator.h>
+#include "x1000.dtsi"
+
+/ {
+ compatible = "ingenic,x1000";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ };
+
+ chosen {
+ stdout-path = &uart2;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x2000000>; /* 32 MiB at 0x0 */
+ };
+};
+
+&ext {
+ clock-frequency = <48000000>;
+};
+
+&msc0 {
+ bus-width = <4>;
+ max-frequency = <6000000>;
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_msc0_pa>;
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_uart2_dataplusflow>;
+};
diff --git a/sys/gnu/dts/mips/ingenic/ci20.dts b/sys/gnu/dts/mips/ingenic/ci20.dts
new file mode 100644
index 000000000000..456c8b83f0dd
--- /dev/null
+++ b/sys/gnu/dts/mips/ingenic/ci20.dts
@@ -0,0 +1,395 @@
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/rfkill-regulator.h>
+#include "jz4780.dtsi"
+
+/ {
+ compatible = "imgtec,ci20", "ingenic,jz4780";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ chosen {
+ stdout-path = &uart4;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x10000000
+ 0x30000000 0x30000000>;
+ };
+
+ audio: audio-ci20 {
+ compatible = "ingenic,ci20-audio";
+ ingenic,i2s-controller = <&i2s>;
+ ingenic,codec = <&codec>;
+ };
+
+ eth0_power: fixedregulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "eth0_power";
+ gpio = <&gpb 25 GPIO_ACTIVE_LOW>;
+ enable-active-high;
+ };
+
+ hdmi_power: fixedregulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "hdmi_power";
+ gpio = <&gpa 25 GPIO_ACTIVE_LOW>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ wifi_power: fixedregulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "wifi_power_gpio";
+ gpio = <&gpb 19 0>;
+ enable-active-high;
+
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ };
+
+ /* HACK: Keeping wifi reset high. No simple driver fix */
+ wifi_reset: fixedregulator@3 {
+ compatible = "regulator-fixed";
+ regulator-name = "wifi_reset_gpio";
+ gpio = <&gpf 7 0>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ /* HACK: Keeping BT reset high. No simple driver fix */
+ bt_reset: fixedregulator@4 {
+ compatible = "regulator-fixed";
+ regulator-name = "bt_reset_gpio";
+ gpio = <&gpf 8 0>;
+ enable-active-high;
+ };
+
+ /* HACK: Keeping BT_reg_on high. No simple driver fix */
+ bt_reg_on: fixedregulator@5 {
+ compatible = "regulator-fixed";
+ regulator-name = "bt_reg_on_gpio";
+ gpio = <&gpf 4 0>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ /* HACK: Keeping BT wake high. No simple driver fix */
+ bt_wake: fixedregulator@6 {
+ compatible = "regulator-fixed";
+ regulator-name = "bt_wake_gpio";
+ gpio = <&gpf 5 0>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ ir: ir-receiver {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpe 3 GPIO_ACTIVE_LOW>;
+ };
+
+ bt-rfkill {
+ compatible = "rfkill-regulator";
+ label = "bt-reset";
+ type = <RFKILL_TYPE_BLUETOOTH>;
+ vrfkill-supply = <&bt_reset>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ led3 {
+ gpios = <&gpc 0 0>;
+ linux,default-trigger = "cpu0";
+ };
+ led2 {
+ gpios = <&gpc 1 0>;
+ linux,default-trigger = "cpu1";
+ };
+ led1 {
+ gpios = <&gpc 2 0>;
+ linux,default-trigger = "nand-disk";
+ };
+ led0 {
+ gpios = <&gpc 3 0>;
+ linux,default-trigger = "none";
+ };
+ };
+};
+
+&ext {
+ clock-frequency = <48000000>;
+};
+
+&msc0 {
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ cd-gpios = <&gpf 20 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_msc0_pe>;
+};
+
+&msc1 {
+ bus-width = <4>;
+ max-frequency = <24000000>;
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_msc1_pd>;
+ vmmc-supply = <&wifi_power>;
+};
+
+&ehci {
+ ingenic,vbus-gpio = <&gpf 15 0>;
+};
+
+&ohci {
+ ingenic,vbus-gpio = <&gpf 15 0>;
+};
+
+&nemc {
+ /*
+ * Only CLE/ALE are needed for the devices that are connected, rather
+ * than the full address line set.
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_nemc_data
+ &pins_nemc_cle_ale
+ &pins_nemc_rd_we
+ &pins_nemc_frd_fwe>;
+
+ nand: nand@1 {
+ compatible = "ingenic,jz4780-nand";
+ reg = <1 0 0x1000000>;
+
+ ingenic,nemc-tAS = <10>;
+ ingenic,nemc-tAH = <5>;
+ ingenic,nemc-tBP = <10>;
+ ingenic,nemc-tAW = <15>;
+ ingenic,nemc-tSTRV = <100>;
+
+ ingenic,bch-device = <&bch>;
+ ingenic,ecc-size = <1024>;
+ ingenic,ecc-strength = <24>;
+
+ ingenic,busy-gpio = <&gpa 20 GPIO_ACTIVE_LOW>;
+ ingenic,wp-gpio = <&gpf 22 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_nemc_cs1>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ partition@0 {
+ label = "u-boot-spl";
+ reg = <0x0 0x0 0x0 0x800000>;
+ };
+
+ partition@0x800000 {
+ label = "u-boot";
+ reg = <0x0 0x800000 0x0 0x200000>;
+ };
+
+ partition@0xa00000 {
+ label = "u-boot-env";
+ reg = <0x0 0xa00000 0x0 0x200000>;
+ };
+
+ partition@0xc00000 {
+ label = "boot";
+ reg = <0x0 0xc00000 0x0 0x4000000>;
+ };
+
+ partition@0x8c00000 {
+ label = "system";
+ reg = <0x0 0x4c00000 0x1 0xfb400000>;
+ };
+ };
+
+ dm9000@6 {
+ compatible = "davicom,dm9000";
+ davicom,no-eeprom;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_nemc_cs6>;
+
+ reg = <6 0x0 1 /* addr */
+ 6 0x2 1>; /* data */
+
+ ingenic,nemc-tAS = <15>;
+ ingenic,nemc-tAH = <10>;
+ ingenic,nemc-tBP = <20>;
+ ingenic,nemc-tAW = <50>;
+ ingenic,nemc-tSTRV = <100>;
+
+ reset-gpios = <&gpf 12 GPIO_ACTIVE_HIGH>;
+ vcc-supply = <&eth0_power>;
+
+ interrupt-parent = <&gpe>;
+ interrupts = <19 0x4>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_uart0_data>;
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_uart1_data>;
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_uart2_dataplusflow>;
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_uart3_data>;
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_uart4_data>;
+};
+
+&i2c0 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_i2c0_data>;
+
+ pmic: act8600@5a {
+ compatible = "active-semi,act8600";
+ reg = <0x5a>;
+
+ regulators {
+ vcore1v_reg: DCDC_REG1 {
+ regulator-name = "vcore1v2";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-always-on;
+ };
+
+ vddmem1v5_reg: DCDC_REG2 {
+ regulator-name = "vddmem1v5";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ };
+
+ vccio3v3_reg: DCDC_REG3 {
+ regulator-name = "vccio3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vcc2v5_reg: LDO_REG5 {
+ regulator-name = "vcc2.5";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ vwifi_reg: LDO_REG6 {
+ regulator-name = "vwifi3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vcim2v8_reg: LDO_REG7 {
+ regulator-name = "vcim2v8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ vcim1v5_reg: LDO_REG8 {
+ regulator-name = "vcim1v5";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ };
+
+ /* Do not disable RTC as they connect to reset line */
+ vrtc1v8_reg: LDO_REG9 {
+ regulator-name = "vrtc1v8";
+ regulator-always-on;
+ };
+
+ vrtc1v1_reg: LDO_REG10 {
+ regulator-name = "vrtc1v2";
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_i2c1_data>;
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_i2c2_data>;
+
+ ov5640@0x3C {
+ compatible = "omnivision,ov5640";
+ reg = <0x3C>;
+
+ core-supply = <&vcim1v5_reg>;
+ analog-supply = <&vcim2v8_reg>;
+
+ gpio-enable = <&gpb 18 0>;
+ gpio-reset = <&gpb 26 0>;
+
+ remote = <&cim>;
+ port {
+ ov5640_1: endpoint {
+ bus-width = <8>;
+ remote-endpoint = <&cim>;
+ };
+ };
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_i2c3_data>;
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_i2c4_data_pf>;
+};
+
+&cim {
+ clock-frequency = <24000000>;
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Parallel bus endpoint */
+ camera: endpoint@0 {
+ reg = <0>; /* Local endpoint # */
+ remote-endpoint = <&ov5640_1>;
+ hsync-active = <1>; /* Active high */
+ vsync-active = <1>; /* Active high */
+ pclk-sample = <0>; /* Falling */
+ };
+ };
+};
diff --git a/sys/gnu/dts/mips/ingenic/jz4780.dtsi b/sys/gnu/dts/mips/ingenic/jz4780.dtsi
new file mode 100644
index 000000000000..c53ee03f4636
--- /dev/null
+++ b/sys/gnu/dts/mips/ingenic/jz4780.dtsi
@@ -0,0 +1,768 @@
+#include <dt-bindings/clock/jz4780-cgu.h>
+#include <dt-bindings/dma/jz4780-dma.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ingenic,jz4780";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "ingenic,xburst";
+ reg = <0>;
+ };
+ cpu1: cpu@1 {
+ compatible = "ingenic,xburst";
+ reg = <1>;
+ clocks = <&cgu JZ4780_CLK_CORE1>;
+ };
+ };
+
+ cpuintc: cpuintc@0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ intc: intc@10001000 {
+ compatible = "ingenic,jz4780-intc";
+ reg = <0x10001000 0x50>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ ext: ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ rtc: rtc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ cgu: jz4780-cgu@10000000 {
+ compatible = "ingenic,jz4780-cgu";
+ reg = <0x10000000 0x100>;
+
+ clocks = <&ext>, <&rtc>;
+ clock-names = "ext", "rtc";
+
+ #clock-cells = <1>;
+ };
+
+ gpu: jz4780-sgx@13040000 {
+ compatible = "ingenic,jz4780-sgx";
+ reg = <0x13040000 0x4000>;
+
+ clocks = <&cgu JZ4780_CLK_GPU>;
+ clock-names = "gpu";
+
+ interrupt-parent = <&intc>;
+ interrupts = <63>;
+ };
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <>;
+
+ tcu@0x10002000 {
+ compatible = "ingenic,jz4780-tcu";
+ reg = <0x10002000 0x140>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <27 26 25>;
+ };
+
+ watchdog: jz47xx-watchdog@0x10002000 {
+ compatible = "ingenic,jz4780-watchdog";
+ reg = <0x10002000 0x100>;
+
+ clocks = <&rtc>;
+ clock-names = "rtc";
+ };
+
+ rtcdev: rtcdev@10003000 {
+ compatible = "ingenic,jz4780-rtc";
+ reg = <0x10003000 0x4c>;
+ interrupt-parent = <&intc>;
+ interrupts = <32>;
+ };
+
+ i2s: i2s@10020000 {
+ compatible = "ingenic,jz4780-i2s";
+ reg = <0x10020000 0x94>;
+
+ clocks = <&cgu JZ4780_CLK_AIC>, <&cgu JZ4780_CLK_I2SPLL>;
+ clock-names = "aic", "i2s";
+
+ dmas = <&dma 0 JZ4780_DMA_I2S0_RX 0xffffffff>, <&dma JZ4780_DMA_I2S0_TX 0 0xffffffff>;
+ dma-names = "rx" , "tx";
+
+ };
+
+ codec: codec@100200a4 {
+ compatible = "ingenic,jz4780-codec";
+ reg = <0x100200a4 0x8>;
+
+ clocks = <&cgu JZ4780_CLK_I2SPLL>;
+ clock-names = "i2s";
+
+ };
+
+ pinctrl@0x10010000 {
+ compatible = "ingenic,jz4780-pinctrl";
+ reg = <0x10010000 0x600>;
+
+ gpa: gpa {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <17>;
+
+ ingenic,pull-ups = <0x3fffffff>;
+ };
+
+ gpb: gpb {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <16>;
+
+ ingenic,pull-downs = <0x000f0c03>;
+ ingenic,pull-ups = <0xfff0030c>;
+ };
+
+ gpc: gpc {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <15>;
+
+ ingenic,pull-ups = <0xffffffff>;
+ };
+
+ gpd: gpd {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <14>;
+
+ ingenic,pull-downs = <0x0000b000>;
+ ingenic,pull-ups = <0xffff4fff>;
+ };
+
+ gpe: gpe {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <13>;
+
+ ingenic,pull-downs = <0x00000483>;
+ ingenic,pull-ups = <0xfffffb7c>;
+ };
+
+ gpf: gpf {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <12>;
+
+ ingenic,pull-downs = <0x00580ff0>;
+ ingenic,pull-ups = <0xffa7f00f>;
+ };
+
+ pincfg_nobias: nobias {
+ bias-disable;
+ };
+
+ pincfg_pull_up: pull_up {
+ bias-pull-up;
+ };
+
+ pincfg_pull_down: pull_down {
+ bias-pull-down;
+ };
+
+ pinfunc_uart0: uart0 {
+ pins_uart0_data: uart0-data {
+ ingenic,pins = <&gpf 0 0 &pincfg_pull_up /* rxd */
+ &gpf 3 0 &pincfg_nobias>; /* txd */
+ };
+
+ pins_uart0_dataplusflow: uart0-dataplusflow {
+ ingenic,pins = <&gpf 0 0 &pincfg_pull_up /* rxd */
+ &gpf 1 0 &pincfg_nobias /* cts */
+ &gpf 2 0 &pincfg_nobias /* rts */
+ &gpf 3 0 &pincfg_nobias>; /* txd */
+ };
+ };
+
+ pinfunc_uart1: uart1 {
+ pins_uart1_data: uart1-data {
+ ingenic,pins = <&gpd 26 0 &pincfg_pull_up /* rxd */
+ &gpd 28 0 &pincfg_nobias>; /* txd */
+ };
+
+ pins_uart1_dataplusflow: uart1-dataplusflow {
+ ingenic,pins = <&gpd 26 0 &pincfg_pull_up /* rxd */
+ &gpd 27 0 &pincfg_nobias /* cts */
+ &gpd 29 0 &pincfg_nobias /* rts */
+ &gpd 28 0 &pincfg_nobias>; /* txd */
+ };
+ };
+
+ pinfunc_uart2: uart2 {
+ pins_uart2_data: uart2-data {
+ ingenic,pins = <&gpd 6 1 &pincfg_nobias /* rxd */
+ &gpd 7 1 &pincfg_nobias>; /* txd */
+ };
+
+ pins_uart2_dataplusflow: uart2-dataplusflow {
+ ingenic,pins = <&gpd 6 1 &pincfg_nobias /* rxd */
+ &gpd 5 1 &pincfg_nobias /* cts */
+ &gpd 4 1 &pincfg_nobias /* rts */
+ &gpd 7 1 &pincfg_nobias>; /* txd */
+ };
+ };
+
+ pinfunc_uart3: uart3 {
+ pins_uart3_data: uart3-data {
+ ingenic,pins = <&gpd 12 0 &pincfg_pull_down /* rxd */
+ &gpe 5 1 &pincfg_nobias>; /* txd */
+ };
+
+ pins_uart3_dataplusflow: uart3-dataplusflow {
+ ingenic,pins = <&gpd 12 0 &pincfg_pull_down /* rxd */
+ &gpe 5 1 &pincfg_nobias /* txd */
+ &gpe 8 0 &pincfg_nobias /* cts */
+ &gpe 9 0 &pincfg_nobias>; /* rts */
+ };
+ };
+
+ pinfunc_uart4: uart4 {
+ pins_uart4_data: uart4-data {
+ ingenic,pins = <&gpc 20 2 &pincfg_pull_up /* rxd */
+ &gpc 10 2 &pincfg_nobias>; /* txd */
+ };
+ };
+
+ pinfunc_msc0: msc0 {
+ pins_msc0_pa: msc0-pa {
+ ingenic,pins = <&gpa 4 1 &pincfg_nobias /* d4 */
+ &gpa 5 1 &pincfg_nobias /* d5 */
+ &gpa 6 1 &pincfg_nobias /* d6 */
+ &gpa 7 1 &pincfg_nobias /* d7 */
+ &gpa 18 1 &pincfg_nobias /* clk */
+ &gpa 19 1 &pincfg_nobias /* cmd */
+ &gpa 20 1 &pincfg_nobias /* d0 */
+ &gpa 21 1 &pincfg_nobias /* d1 */
+ &gpa 22 1 &pincfg_nobias /* d2 */
+ &gpa 23 1 &pincfg_nobias /* d3 */
+ &gpa 24 1 &pincfg_nobias>; /* rst */
+ };
+
+ pins_msc0_pe: msc0-pe {
+ ingenic,pins = <&gpe 20 0 &pincfg_nobias /* d0 */
+ &gpe 21 0 &pincfg_nobias /* d1 */
+ &gpe 22 0 &pincfg_nobias /* d2 */
+ &gpe 23 0 &pincfg_nobias /* d3 */
+ &gpe 28 0 &pincfg_nobias /* clk */
+ &gpe 29 0 &pincfg_nobias>; /* cmd */
+ };
+ };
+
+ pinfunc_msc1: msc1 {
+ pins_msc1_pd: msc1-pd {
+ ingenic,pins = <&gpd 20 0 &pincfg_nobias /* d0 */
+ &gpd 21 0 &pincfg_nobias /* d1 */
+ &gpd 22 0 &pincfg_nobias /* d2 */
+ &gpd 23 0 &pincfg_nobias /* d3 */
+ &gpd 24 0 &pincfg_nobias /* clk */
+ &gpd 25 0 &pincfg_nobias>; /* cmd */
+ };
+
+ pins_msc1_pe: msc1-pe {
+ ingenic,pins = <&gpe 20 1 &pincfg_nobias /* d0 */
+ &gpe 21 1 &pincfg_nobias /* d1 */
+ &gpe 22 1 &pincfg_nobias /* d2 */
+ &gpe 23 1 &pincfg_nobias /* d3 */
+ &gpe 28 1 &pincfg_nobias /* clk */
+ &gpe 29 1 &pincfg_nobias>; /* cmd */
+ };
+ };
+
+ pinfunc_nemc: nemc {
+ pins_nemc_data: nemc-data {
+ ingenic,pins = <&gpa 0 0 &pincfg_nobias /* sd0 */
+ &gpa 1 0 &pincfg_nobias /* sd1 */
+ &gpa 2 0 &pincfg_nobias /* sd2 */
+ &gpa 3 0 &pincfg_nobias /* sd3 */
+ &gpa 4 0 &pincfg_nobias /* sd4 */
+ &gpa 5 0 &pincfg_nobias /* sd5 */
+ &gpa 6 0 &pincfg_nobias /* sd6 */
+ &gpa 7 0 &pincfg_nobias>; /* sd7 */
+ };
+
+ pins_nemc_cle_ale: nemc-cle-ale {
+ ingenic,pins = <&gpb 0 0 &pincfg_nobias /* sa0_cl */
+ &gpb 1 0 &pincfg_nobias>; /* sa1_al */
+ };
+
+ pins_nemc_addr: nemc-addr {
+ ingenic,pins = <&gpb 0 0 &pincfg_nobias /* sa0_cl */
+ &gpb 1 0 &pincfg_nobias /* sa1_al */
+ &gpb 2 0 &pincfg_nobias /* sa2 */
+ &gpb 3 0 &pincfg_nobias /* sa3 */
+ &gpb 4 0 &pincfg_nobias /* sa4 */
+ &gpb 5 0 &pincfg_nobias>; /* sa5 */
+ };
+
+ pins_nemc_rd_we: nemc-rd-we {
+ ingenic,pins = <&gpa 16 0 &pincfg_nobias /* rd */
+ &gpa 17 0 &pincfg_nobias>; /* we */
+ };
+
+ pins_nemc_frd_fwe: nemc-frd-fwe {
+ ingenic,pins = <&gpa 18 0 &pincfg_nobias /* rd */
+ &gpa 19 0 &pincfg_nobias>; /* we */
+ };
+
+ pins_nemc_cs1: nemc-cs1 {
+ ingenic,pins = <&gpa 21 0 &pincfg_nobias>; /* cs1 */
+ };
+
+ pins_nemc_cs6: nemc-cs6 {
+ ingenic,pins = <&gpa 26 0 &pincfg_nobias>; /* cs6 */
+ };
+ };
+
+ pinfunc_i2c0: i2c0 {
+ pins_i2c0_data: i2c0-data{
+ ingenic,pins = <&gpd 30 0 &pincfg_nobias /* sda */
+ &gpd 31 0 &pincfg_nobias>; /* sck */
+ };
+ };
+
+ pinfunc_i2c1: i2c1 {
+ pins_i2c1_data: i2c1-data{
+ ingenic,pins = <&gpe 30 0 &pincfg_nobias /* sda */
+ &gpe 31 0 &pincfg_nobias>; /* sck */
+ };
+ };
+
+ pinfunc_i2c2: i2c2 {
+ pins_i2c2_data: i2c2-data{
+ ingenic,pins = <&gpf 16 2 &pincfg_nobias /* sda */
+ &gpf 17 2 &pincfg_nobias>; /* sck */
+ };
+ };
+
+ pinfunc_i2c3: i2c3 {
+ pins_i2c3_data: i2c3-data{
+ ingenic,pins = <&gpd 10 1 &pincfg_nobias /* sda */
+ &gpd 11 1 &pincfg_nobias>; /* sck */
+ };
+ };
+
+ pinfunc_i2c4: i2c4 {
+ pins_i2c4_data: i2c4-data-pe{
+ ingenic,pins = <&gpe 12 1 &pincfg_nobias /* sda */
+ &gpe 13 1 &pincfg_nobias>; /* sck */
+ };
+
+ pins_i2c4_data_pf: i2c4-data-pf{
+ ingenic,pins = <&gpf 25 1 &pincfg_nobias /* hdmi_sda */
+ &gpf 24 1 &pincfg_nobias>; /* hdmi_sck */
+ };
+ };
+
+ pinfunc_cim: cim {
+ pins_cim: cim-pb {
+ ingenic,pins = <&gpb 6 0 &pincfg_nobias
+ &gpb 7 0 &pincfg_nobias
+ &gpb 8 0 &pincfg_nobias
+ &gpb 9 0 &pincfg_nobias
+ &gpb 10 0 &pincfg_nobias
+ &gpb 11 0 &pincfg_nobias
+ &gpb 12 0 &pincfg_nobias
+ &gpb 13 0 &pincfg_nobias
+ &gpb 14 0 &pincfg_nobias
+ &gpb 15 0 &pincfg_nobias
+ &gpb 16 0 &pincfg_nobias
+ &gpb 17 0 &pincfg_nobias>;
+ };
+ };
+ };
+
+ spi_gpio {
+ compatible = "spi-gpio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-chipselects = <2>;
+
+ gpio-miso = <&gpe 14 0>;
+ gpio-sck = <&gpe 15 0>;
+ gpio-mosi = <&gpe 17 0>;
+ cs-gpios = <&gpe 16 0
+ &gpe 18 0>;
+
+ spidev@0 {
+ compatible = "spidev";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+
+ uart0: serial@10030000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10030000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <51>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART0>;
+ clock-names = "baud", "module";
+ };
+
+ uart1: serial@10031000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10031000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <50>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART1>;
+ clock-names = "baud", "module";
+ };
+
+ uart2: serial@10032000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10032000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <49>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART2>;
+ clock-names = "baud", "module";
+ };
+
+ uart3: serial@10033000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10033000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <48>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART3>;
+ clock-names = "baud", "module";
+ };
+
+ uart4: serial@10034000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10034000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <34>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART4>;
+ clock-names = "baud", "module";
+ };
+
+ i2c0: i2c0@0x10050000 {
+ compatible = "ingenic,jz4780-i2c";
+ reg = <0x10050000 0x1000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <60>;
+
+ clocks = <&cgu JZ4780_CLK_SMB0>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c1@0x10051000 {
+ compatible = "ingenic,jz4780-i2c";
+ reg = <0x10051000 0x1000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <59>;
+
+ clocks = <&cgu JZ4780_CLK_SMB1>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c2@0x10052000 {
+ compatible = "ingenic,jz4780-i2c";
+ reg = <0x10052000 0x1000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <58>;
+
+ clocks = <&cgu JZ4780_CLK_SMB2>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c3: i2c3@0x10053000 {
+ compatible = "ingenic,jz4780-i2c";
+ reg = <0x10053000 0x1000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <57>;
+
+ clocks = <&cgu JZ4780_CLK_SMB3>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c4: i2c4@0x10054000 {
+ compatible = "ingenic,jz4780-i2c";
+ reg = <0x10054000 0x1000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <56>;
+
+ clocks = <&cgu JZ4780_CLK_SMB4>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ lpcr: lcr@0x10000004 {
+ compatible = "ingenic,jz4780-lcr";
+ reg = <0x10000004 0x4>;
+
+ regulators {
+ vpu_power: VPU {
+ };
+ gpu_power: GPU {
+ };
+ gps_power: GPS {
+ };
+ };
+ };
+
+ adc@0x10070000 {
+ compatible = "ingenic,jz4780-adc";
+ reg = <0x10070000 0x30>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <18>;
+
+ clocks = <&cgu JZ4780_CLK_SADC>;
+ clock-names = "adc";
+ };
+ };
+
+ ahb2 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <>;
+
+
+ lcd: jz4780-lcdk@0x13050000 {
+ compatible = "ingenic,jz4780-lcd";
+ reg = <0x13050000 0x1800>;
+
+ clocks = <&cgu JZ4780_CLK_TVE>, <&cgu JZ4780_CLK_LCD0PIXCLK>;
+ clock-names = "lcd_clk", "lcd_pixclk";
+
+ interrupt-parent = <&intc>;
+ interrupts = <31>;
+
+ hdmi = <&hdmi>;
+ ddc = <&i2c4>;
+ };
+
+ cim: jz4780-cim@0x13060000 {
+ compatible = "ingenic,jz4780-cim";
+ reg = <0x13060000 0x68>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <30>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_cim>;
+
+ clocks = <&cgu JZ4780_CLK_CIM>, <&cgu JZ4780_CLK_CIMMCLK>;
+ clock-names = "cim", "module";
+ };
+
+ hdmi: jz4780-hdmi3@0x10180000 {
+ compatible = "synopsys,dwc-hdmi";
+ reg = <0x10180000 0x8000>;
+ reg-shift = <2>;
+
+ clocks = <&cgu JZ4780_CLK_HDMI>, <&cgu JZ4780_CLK_AHB0>;
+ clock-names = "hdmi" , "ahb";
+
+ clock-frequency = <27000000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <3>;
+
+ ddc = <&i2c4>;
+ };
+
+
+ nemc: nemc@13410000 {
+ compatible = "ingenic,jz4780-nemc";
+ reg = <0x13410000 0x10000>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <1 0 0x1b000000 0x1000000
+ 2 0 0x1a000000 0x1000000
+ 3 0 0x19000000 0x1000000
+ 4 0 0x18000000 0x1000000
+ 5 0 0x17000000 0x1000000
+ 6 0 0x16000000 0x1000000>;
+
+ clocks = <&cgu JZ4780_CLK_NEMC>;
+ };
+
+ efuse: efuse@134100D0 {
+ compatible = "ingenic,jz4780-efuse";
+ reg = <0x134100D0 0xFF>;
+
+ clocks = <&cgu JZ4780_CLK_AHB2>;
+ clock-names = "bus_clk";
+ };
+
+ dma: dma@13420000 {
+ compatible = "ingenic,jz4780-dma";
+ reg = <0x13420000 0x10000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <10>;
+
+ clocks = <&cgu JZ4780_CLK_PDMA>;
+
+ #dma-cells = <3>;
+ };
+
+ msc0: msc@13450000 {
+ compatible = "ingenic,jz4780-mmc";
+ reg = <0x13450000 0x1000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <37>;
+
+ clocks = <&cgu JZ4780_CLK_MSC0>;
+ clock-names = "mmc";
+
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ cap-sdio-irq;
+
+ dmas = <&dma JZ4780_DMA_MSC0_TX JZ4780_DMA_MSC0_RX 0xffffffff>;
+ dma-names = "rx-tx";
+ };
+
+ msc1: msc@13460000 {
+ compatible = "ingenic,jz4780-mmc";
+ reg = <0x13460000 0x1000>;
+
+ status = "disabled";
+
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+
+ clocks = <&cgu JZ4780_CLK_MSC1>;
+ clock-names = "mmc";
+
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ cap-sdio-irq;
+
+ dmas = <&dma JZ4780_DMA_MSC1_TX JZ4780_DMA_MSC1_RX 0xffffffff>;
+ dma-names = "rx-tx";
+ };
+
+ ehci: jz4780-ehci@0x13490000 {
+ compatible = "ingenic,jz4780-ehci";
+ reg = <0x13490000 0x10000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <20>;
+
+ clocks = <&cgu JZ4780_CLK_UHC>;
+ };
+
+ ohci: jz4780-ohci@0x134a0000 {
+ compatible = "ingenic,jz4780-ohci";
+ reg = <0x134a0000 0x10000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <5>;
+
+ clocks = <&cgu JZ4780_CLK_UHC>;
+ clock-names = "uhc";
+ };
+
+ bch: bch@134d0000 {
+ compatible = "ingenic,jz4780-bch";
+ reg = <0x134d0000 0x10000>;
+
+ clocks = <&cgu JZ4780_CLK_BCH>;
+ };
+
+ otg: jz4780-otg@0x13500000 {
+ compatible = "ingenic,jz4780-otg";
+ reg = <0x13500000 0x40000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <21>;
+
+ clocks = <&cgu JZ4780_CLK_OTGPHY>, <&cgu JZ4780_CLK_OTG1>;
+ clock-names = "otg_phy", "otg1";
+ };
+ };
+};
diff --git a/sys/gnu/dts/mips/ingenic/x1000.dtsi b/sys/gnu/dts/mips/ingenic/x1000.dtsi
new file mode 100644
index 000000000000..dd0105e04e51
--- /dev/null
+++ b/sys/gnu/dts/mips/ingenic/x1000.dtsi
@@ -0,0 +1,420 @@
+#include <dt-bindings/clock/jz4780-cgu.h>
+#include <dt-bindings/dma/jz4780-dma.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ingenic,x1000";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "ingenic,xburst";
+ reg = <0>;
+ };
+ };
+
+ cpuintc: cpuintc@0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ intc: intc@10001000 {
+ compatible = "ingenic,jz4780-intc";
+ reg = <0x10001000 0x50>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ ext: ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ rtc: rtc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ cgu: jz4780-cgu@10000000 {
+ compatible = "ingenic,jz4780-cgu";
+ reg = <0x10000000 0x100>;
+
+ clocks = <&ext>, <&rtc>;
+ clock-names = "ext", "rtc";
+
+ #clock-cells = <1>;
+ };
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <>;
+
+ tcu@0x10002000 {
+ compatible = "ingenic,jz4780-tcu";
+ reg = <0x10002000 0x140>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <27 26 25>;
+ };
+
+ watchdog: jz47xx-watchdog@0x10002000 {
+ compatible = "ingenic,jz4780-watchdog";
+ reg = <0x10002000 0x100>;
+
+ clocks = <&rtc>;
+ clock-names = "rtc";
+ };
+
+ rtcdev: rtcdev@10003000 {
+ compatible = "ingenic,jz4780-rtc";
+ reg = <0x10003000 0x4c>;
+ interrupt-parent = <&intc>;
+ interrupts = <32>;
+ };
+
+ i2s: i2s@10020000 {
+ compatible = "ingenic,jz4780-i2s";
+ reg = <0x10020000 0x94>;
+
+ clocks = <&cgu JZ4780_CLK_AIC>, <&cgu JZ4780_CLK_I2SPLL>;
+ clock-names = "aic", "i2s";
+
+ dmas = <&dma 0 JZ4780_DMA_I2S0_RX 0xffffffff>, <&dma JZ4780_DMA_I2S0_TX 0 0xffffffff>;
+ dma-names = "rx" , "tx";
+
+ };
+
+ codec: codec@100200a4 {
+ compatible = "ingenic,jz4780-codec";
+ reg = <0x100200a4 0x8>;
+
+ clocks = <&cgu JZ4780_CLK_I2SPLL>;
+ clock-names = "i2s";
+
+ };
+
+ pinctrl@0x10010000 {
+ compatible = "ingenic,jz4780-pinctrl";
+ reg = <0x10010000 0x600>;
+
+ gpa: gpa {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <17>;
+
+ ingenic,pull-ups = <0x3fffffff>;
+ };
+
+ gpb: gpb {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <16>;
+
+ ingenic,pull-downs = <0x000f0c03>;
+ ingenic,pull-ups = <0xfff0030c>;
+ };
+
+ gpc: gpc {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <15>;
+
+ ingenic,pull-ups = <0xffffffff>;
+ };
+
+ gpd: gpd {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <14>;
+
+ ingenic,pull-downs = <0x0000b000>;
+ ingenic,pull-ups = <0xffff4fff>;
+ };
+
+ pincfg_nobias: nobias {
+ bias-disable;
+ };
+
+ pincfg_pull_up: pull_up {
+ bias-pull-up;
+ };
+
+ pincfg_pull_down: pull_down {
+ bias-pull-down;
+ };
+
+ pinfunc_uart2: uart2 {
+ pins_uart2_data: uart2-data {
+ ingenic,pins = <&gpd 6 1 &pincfg_nobias /* rxd */
+ &gpd 7 1 &pincfg_nobias>; /* txd */
+ };
+
+ pins_uart2_dataplusflow: uart2-dataplusflow {
+ ingenic,pins = <&gpd 6 1 &pincfg_nobias /* rxd */
+ &gpd 5 1 &pincfg_nobias /* cts */
+ &gpd 4 1 &pincfg_nobias /* rts */
+ &gpd 7 1 &pincfg_nobias>; /* txd */
+ };
+ };
+
+ pinfunc_msc0: msc0 {
+ pins_msc0_pa: msc0-pa {
+ ingenic,pins = <&gpa 16 1 &pincfg_nobias /* d7 */
+ &gpa 17 1 &pincfg_nobias /* d6 */
+ &gpa 18 1 &pincfg_nobias /* d5 */
+ &gpa 19 1 &pincfg_nobias /* d4 */
+ &gpa 20 1 &pincfg_nobias /* d3 */
+ &gpa 21 1 &pincfg_nobias /* d2 */
+ &gpa 22 1 &pincfg_nobias /* d1 */
+ &gpa 23 1 &pincfg_nobias /* d0 */
+ &gpa 24 1 &pincfg_nobias /* clk */
+ &gpa 25 1 &pincfg_nobias>; /* cmd */
+ };
+ };
+
+ pinfunc_cim: cim {
+ pins_cim: cim-pb {
+ ingenic,pins = < /* Fill me. */ >;
+ };
+ };
+ };
+
+ uart0: serial@10030000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10030000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <51>;
+ status = "disabled";
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART0>;
+ clock-names = "baud", "module";
+ };
+
+ uart1: serial@10031000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10031000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <50>;
+ status = "disabled";
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART1>;
+ clock-names = "baud", "module";
+ };
+
+ uart2: serial@10032000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10032000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <49>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART2>;
+ clock-names = "baud", "module";
+ };
+
+ uart3: serial@10033000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10033000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <48>;
+ status = "disabled";
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART3>;
+ clock-names = "baud", "module";
+ };
+
+ i2c0: i2c0@0x10050000 {
+ compatible = "ingenic,jz4780-i2c";
+ reg = <0x10050000 0x1000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <60>;
+
+ clocks = <&cgu JZ4780_CLK_SMB0>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c1@0x10051000 {
+ compatible = "ingenic,jz4780-i2c";
+ reg = <0x10051000 0x1000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <59>;
+
+ clocks = <&cgu JZ4780_CLK_SMB1>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c2@0x10052000 {
+ compatible = "ingenic,jz4780-i2c";
+ reg = <0x10052000 0x1000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <58>;
+
+ clocks = <&cgu JZ4780_CLK_SMB2>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ lpcr: lcr@0x10000004 {
+ compatible = "ingenic,jz4780-lcr";
+ reg = <0x10000004 0x4>;
+
+ regulators {
+ vpu_power: VPU {
+ };
+ gpu_power: GPU {
+ };
+ gps_power: GPS {
+ };
+ };
+ };
+ };
+
+ ahb2 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <>;
+
+ lcd: jz4780-lcdk@0x13050000 {
+ compatible = "ingenic,jz4780-lcd";
+ reg = <0x13050000 0x1800>;
+
+ clocks = <&cgu JZ4780_CLK_TVE>, <&cgu JZ4780_CLK_LCD0PIXCLK>;
+ clock-names = "lcd_clk", "lcd_pixclk";
+
+ interrupt-parent = <&intc>;
+ interrupts = <31>;
+ };
+
+ cim: jz4780-cim@0x13060000 {
+ compatible = "ingenic,jz4780-cim";
+ reg = <0x13060000 0x68>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <30>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_cim>;
+
+ clocks = <&cgu JZ4780_CLK_CIM>, <&cgu JZ4780_CLK_CIMMCLK>;
+ clock-names = "cim", "module";
+ };
+
+ efuse: efuse@13540000 {
+ compatible = "ingenic,jz4780-efuse";
+ reg = <0x13540000 0xFF>;
+
+ clocks = <&cgu JZ4780_CLK_AHB2>;
+ clock-names = "bus_clk";
+ };
+
+ dma: dma@13420000 {
+ compatible = "ingenic,jz4780-dma";
+ reg = <0x13420000 0x10000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <10>;
+
+ clocks = <&cgu JZ4780_CLK_PDMA>;
+
+ #dma-cells = <3>;
+ };
+
+ msc0: msc@13450000 {
+ compatible = "ingenic,jz4780-mmc";
+ reg = <0x13450000 0x1000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <37>;
+
+ clocks = <&cgu JZ4780_CLK_MSC0>;
+ clock-names = "mmc";
+
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ cap-sdio-irq;
+
+ dmas = <&dma JZ4780_DMA_MSC0_TX JZ4780_DMA_MSC0_RX 0xffffffff>;
+ dma-names = "rx-tx";
+ };
+
+ msc1: msc@13460000 {
+ compatible = "ingenic,jz4780-mmc";
+ reg = <0x13460000 0x1000>;
+
+ status = "disabled";
+
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+
+ clocks = <&cgu JZ4780_CLK_MSC1>;
+ clock-names = "mmc";
+
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ cap-sdio-irq;
+
+ dmas = <&dma JZ4780_DMA_MSC1_TX JZ4780_DMA_MSC1_RX 0xffffffff>;
+ dma-names = "rx-tx";
+ };
+
+ otg: jz4780-otg@0x13500000 {
+ compatible = "ingenic,jz4780-otg";
+ reg = <0x13500000 0x40000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <21>;
+
+ clocks = <&cgu JZ4780_CLK_OTGPHY>, <&cgu JZ4780_CLK_OTG1>;
+ clock-names = "otg_phy", "otg1";
+ };
+ };
+};
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 3cf0c5a66589..2ab8d1b485ce 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -857,6 +857,14 @@ trap_pfault(frame, usermode, eva)
}
/*
+ * If the trap was caused by errant bits in the PTE then panic.
+ */
+ if (frame->tf_err & PGEX_RSV) {
+ trap_fatal(frame, eva);
+ return (-1);
+ }
+
+ /*
* PGEX_I is defined only if the execute disable bit capability is
* supported and enabled.
*/
@@ -926,9 +934,15 @@ trap_fatal(frame, eva)
#endif
if (type == T_PAGEFLT) {
printf("fault virtual address = 0x%x\n", eva);
- printf("fault code = %s %s, %s\n",
+ printf("fault code = %s %s%s, %s\n",
code & PGEX_U ? "user" : "supervisor",
code & PGEX_W ? "write" : "read",
+#if defined(PAE) || defined(PAE_TABLES)
+ pg_nx != 0 ?
+ (code & PGEX_I ? " instruction" : " data") :
+#endif
+ "",
+ code & PGEX_RSV ? "reserved bits in PTE" :
code & PGEX_P ? "protection violation" : "page not present");
}
printf("instruction pointer = 0x%x:0x%x\n",
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 7d9adb050213..1a41aac581d4 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1006,7 +1006,7 @@ exec_map_first_page(imgp)
break;
} else {
ma[i] = vm_page_alloc(object, i,
- VM_ALLOC_NORMAL | VM_ALLOC_IFNOTCACHED);
+ VM_ALLOC_NORMAL);
if (ma[i] == NULL)
break;
}
diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c
index cac4d3649e64..2b21b3831d0b 100644
--- a/sys/kern/kern_sendfile.c
+++ b/sys/kern/kern_sendfile.c
@@ -62,6 +62,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_object.h>
#include <vm/vm_pager.h>
+extern vm_page_t bogus_page;
+
/*
* Structure describing a single sendfile(2) I/O, which may consist of
* several underlying pager I/Os.
@@ -258,7 +260,8 @@ sendfile_iodone(void *arg, vm_page_t *pg, int count, int error)
struct socket *so;
for (int i = 0; i < count; i++)
- vm_page_xunbusy(pg[i]);
+ if (pg[i] != bogus_page)
+ vm_page_xunbusy(pg[i]);
if (error)
sfio->error = error;
@@ -341,51 +344,53 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, off_t off, off_t len,
}
/*
- * Now 'i' points to first invalid page, iterate further
- * to make 'j' point at first valid after a bunch of
- * invalid ones.
- */
- for (j = i + 1; j < npages; j++)
- if (vm_page_is_valid(pa[j], vmoff(j, off) & PAGE_MASK,
- xfsize(j, npages, off, len))) {
- SFSTAT_INC(sf_pages_valid);
- break;
- }
-
- /*
- * Now we got region of invalid pages between 'i' and 'j'.
- * Check that they belong to pager. They may not be there,
- * which is a regular situation for shmem pager. For vnode
- * pager this happens only in case of sparse file.
+ * Next page is invalid. Check if it belongs to pager. It
+ * may not be there, which is a regular situation for shmem
+ * pager. For vnode pager this happens only in case of
+ * a sparse file.
*
* Important feature of vm_pager_has_page() is the hint
* stored in 'a', about how many pages we can pagein after
* this page in a single I/O.
*/
- while (!vm_pager_has_page(obj, OFF_TO_IDX(vmoff(i, off)),
- NULL, &a) && i < j) {
+ if (!vm_pager_has_page(obj, OFF_TO_IDX(vmoff(i, off)), NULL,
+ &a)) {
pmap_zero_page(pa[i]);
pa[i]->valid = VM_PAGE_BITS_ALL;
pa[i]->dirty = 0;
vm_page_xunbusy(pa[i]);
i++;
- }
- if (i == j)
continue;
+ }
/*
* We want to pagein as many pages as possible, limited only
* by the 'a' hint and actual request.
- *
- * We should not pagein into already valid page, thus if
- * 'j' didn't reach last page, trim by that page.
- *
- * When the pagein fulfils the request, also specify readahead.
*/
- if (j < npages)
- a = min(a, j - i - 1);
count = min(a + 1, npages - i);
+ /*
+ * We should not pagein into a valid page, thus we first trim
+ * any valid pages off the end of request, and substitute
+ * to bogus_page those, that are in the middle.
+ */
+ for (j = i + count - 1; j > i; j--) {
+ if (vm_page_is_valid(pa[j], vmoff(j, off) & PAGE_MASK,
+ xfsize(j, npages, off, len))) {
+ count--;
+ rhpages = 0;
+ } else
+ break;
+ }
+ for (j = i + 1; j < i + count - 1; j++)
+ if (vm_page_is_valid(pa[j], vmoff(j, off) & PAGE_MASK,
+ xfsize(j, npages, off, len))) {
+ vm_page_xunbusy(pa[j]);
+ SFSTAT_INC(sf_pages_valid);
+ SFSTAT_INC(sf_pages_bogus);
+ pa[j] = bogus_page;
+ }
+
refcount_acquire(&sfio->nios);
rv = vm_pager_get_pages_async(obj, pa + i, count, NULL,
i + count == npages ? &rhpages : NULL,
@@ -398,13 +403,18 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, off_t off, off_t len,
if (i + count == npages)
SFSTAT_ADD(sf_rhpages_read, rhpages);
-#ifdef INVARIANTS
- for (j = i; j < i + count && j < npages; j++)
- KASSERT(pa[j] == vm_page_lookup(obj,
- OFF_TO_IDX(vmoff(j, off))),
- ("pa[j] %p lookup %p\n", pa[j],
- vm_page_lookup(obj, OFF_TO_IDX(vmoff(j, off)))));
-#endif
+ /*
+ * Restore the valid page pointers. They are already
+ * unbusied, but still wired.
+ */
+ for (j = i; j < i + count; j++)
+ if (pa[j] == bogus_page) {
+ pa[j] = vm_page_lookup(obj,
+ OFF_TO_IDX(vmoff(j, off)));
+ KASSERT(pa[j], ("%s: page %p[%d] disappeared",
+ __func__, pa, j));
+
+ }
i += count;
nios++;
}
@@ -696,13 +706,20 @@ retry_space:
/*
* Calculate maximum allowed number of pages for readahead
- * at this iteration. First, we allow readahead up to "rem".
+ * at this iteration. If SF_USER_READAHEAD was set, we don't
+ * do any heuristics and use exactly the value supplied by
+ * application. Otherwise, we allow readahead up to "rem".
* If application wants more, let it be, but there is no
* reason to go above MAXPHYS. Also check against "obj_size",
* since vm_pager_has_page() can hint beyond EOF.
*/
- rhpages = howmany(rem + (off & PAGE_MASK), PAGE_SIZE) - npages;
- rhpages += SF_READAHEAD(flags);
+ if (flags & SF_USER_READAHEAD) {
+ rhpages = SF_READAHEAD(flags);
+ } else {
+ rhpages = howmany(rem + (off & PAGE_MASK), PAGE_SIZE) -
+ npages;
+ rhpages += SF_READAHEAD(flags);
+ }
rhpages = min(howmany(MAXPHYS, PAGE_SIZE), rhpages);
rhpages = min(howmany(obj_size - trunc_page(off), PAGE_SIZE) -
npages, rhpages);
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index ae2dfcd52ec2..2bdc2bf8d81c 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -198,7 +198,9 @@ struct umtxq_chain {
PRI_MAX_TIMESHARE : (td)->td_user_pri)
#define GOLDEN_RATIO_PRIME 2654404609U
+#ifndef UMTX_CHAINS
#define UMTX_CHAINS 512
+#endif
#define UMTX_SHIFTS (__WORD_BIT - 9)
#define GET_SHARE(flags) \
diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c
index 82dc6e9ecdb2..f97da1714681 100644
--- a/sys/kern/sched_4bsd.c
+++ b/sys/kern/sched_4bsd.c
@@ -308,9 +308,8 @@ maybe_resched(struct thread *td)
/*
* This function is called when a thread is about to be put on run queue
* because it has been made runnable or its priority has been adjusted. It
- * determines if the new thread should be immediately preempted to. If so,
- * it switches to it and eventually returns true. If not, it returns false
- * so that the caller may place the thread on an appropriate run queue.
+ * determines if the new thread should preempt the current thread. If so,
+ * it sets td_owepreempt to request a preemption.
*/
int
maybe_preempt(struct thread *td)
@@ -327,7 +326,6 @@ maybe_preempt(struct thread *td)
* - The current thread has a higher (numerically lower) or
* equivalent priority. Note that this prevents curthread from
* trying to preempt to itself.
- * - It is too early in the boot for context switches (cold is set).
* - The current thread has an inhibitor set or is in the process of
* exiting. In this case, the current thread is about to switch
* out anyways, so there's no point in preempting. If we did,
@@ -348,7 +346,7 @@ maybe_preempt(struct thread *td)
("maybe_preempt: trying to run inhibited thread"));
pri = td->td_priority;
cpri = ctd->td_priority;
- if (panicstr != NULL || pri >= cpri || cold /* || dumping */ ||
+ if (panicstr != NULL || pri >= cpri /* || dumping */ ||
TD_IS_INHIBITED(ctd))
return (0);
#ifndef FULL_PREEMPTION
@@ -356,29 +354,8 @@ maybe_preempt(struct thread *td)
return (0);
#endif
- if (ctd->td_critnest > 1) {
- CTR1(KTR_PROC, "maybe_preempt: in critical section %d",
- ctd->td_critnest);
- ctd->td_owepreempt = 1;
- return (0);
- }
- /*
- * Thread is runnable but not yet put on system run queue.
- */
- MPASS(ctd->td_lock == td->td_lock);
- MPASS(TD_ON_RUNQ(td));
- TD_SET_RUNNING(td);
- CTR3(KTR_PROC, "preempting to thread %p (pid %d, %s)\n", td,
- td->td_proc->p_pid, td->td_name);
- mi_switch(SW_INVOL | SW_PREEMPT | SWT_PREEMPT, td);
- /*
- * td's lock pointer may have changed. We have to return with it
- * locked.
- */
- spinlock_enter();
- thread_unlock(ctd);
- thread_lock(td);
- spinlock_exit();
+ CTR0(KTR_PROC, "maybe_preempt: scheduling preemption");
+ ctd->td_owepreempt = 1;
return (1);
#else
return (0);
@@ -1127,7 +1104,7 @@ forward_wakeup(int cpunum)
if ((!forward_wakeup_enabled) ||
(forward_wakeup_use_mask == 0 && forward_wakeup_use_loop == 0))
return (0);
- if (!smp_started || cold || panicstr)
+ if (!smp_started || panicstr)
return (0);
forward_wakeups_requested++;
@@ -1332,6 +1309,12 @@ sched_add(struct thread *td, int flags)
ts->ts_runq = &runq;
}
+ if ((td->td_flags & TDF_NOLOAD) == 0)
+ sched_load_add();
+ runq_add(ts->ts_runq, td, flags);
+ if (cpu != NOCPU)
+ runq_length[cpu]++;
+
cpuid = PCPU_GET(cpuid);
if (single_cpu && cpu != cpuid) {
kick_other_cpu(td->td_priority, cpu);
@@ -1348,18 +1331,10 @@ sched_add(struct thread *td, int flags)
}
if (!forwarded) {
- if ((flags & SRQ_YIELDING) == 0 && maybe_preempt(td))
- return;
- else
+ if (!maybe_preempt(td))
maybe_resched(td);
}
}
-
- if ((td->td_flags & TDF_NOLOAD) == 0)
- sched_load_add();
- runq_add(ts->ts_runq, td, flags);
- if (cpu != NOCPU)
- runq_length[cpu]++;
}
#else /* SMP */
{
@@ -1393,23 +1368,11 @@ sched_add(struct thread *td, int flags)
CTR2(KTR_RUNQ, "sched_add: adding td_sched:%p (td:%p) to runq", ts, td);
ts->ts_runq = &runq;
- /*
- * If we are yielding (on the way out anyhow) or the thread
- * being saved is US, then don't try be smart about preemption
- * or kicking off another CPU as it won't help and may hinder.
- * In the YIEDLING case, we are about to run whoever is being
- * put in the queue anyhow, and in the OURSELF case, we are
- * putting ourself on the run queue which also only happens
- * when we are about to yield.
- */
- if ((flags & SRQ_YIELDING) == 0) {
- if (maybe_preempt(td))
- return;
- }
if ((td->td_flags & TDF_NOLOAD) == 0)
sched_load_add();
runq_add(ts->ts_runq, td, flags);
- maybe_resched(td);
+ if (!maybe_preempt(td))
+ maybe_resched(td);
}
#endif /* SMP */
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index d80c3d91075e..91dc30b9109d 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD$");
#include "opt_bus.h"
+#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
@@ -65,6 +66,8 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
#include <vm/vm.h>
+#include <ddb/ddb.h>
+
SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL);
SYSCTL_ROOT_NODE(OID_AUTO, dev, CTLFLAG_RW, NULL, NULL);
@@ -143,6 +146,9 @@ static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc");
static void devctl2_init(void);
+#define DRIVERNAME(d) ((d)? d->name : "no driver")
+#define DEVCLANAME(d) ((d)? d->name : "no devclass")
+
#ifdef BUS_DEBUG
static int bus_debug = 1;
@@ -151,8 +157,6 @@ SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RWTUN, &bus_debug, 0,
#define PDEBUG(a) if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");}
#define DEVICENAME(d) ((d)? device_get_name(d): "no device")
-#define DRIVERNAME(d) ((d)? d->name : "no driver")
-#define DEVCLANAME(d) ((d)? d->name : "no devclass")
/**
* Produce the indenting, indent*2 spaces plus a '.' ahead of that to
@@ -176,8 +180,6 @@ void print_devclass_list(void);
/* Make the compiler ignore the function calls */
#define PDEBUG(a) /* nop */
#define DEVICENAME(d) /* nop */
-#define DRIVERNAME(d) /* nop */
-#define DEVCLANAME(d) /* nop */
#define print_device_short(d,i) /* nop */
#define print_device(d,i) /* nop */
@@ -5586,3 +5588,32 @@ devctl2_init(void)
make_dev_credf(MAKEDEV_ETERNAL, &devctl2_cdevsw, 0, NULL,
UID_ROOT, GID_WHEEL, 0600, "devctl2");
}
+
+#ifdef DDB
+DB_SHOW_COMMAND(device, db_show_device)
+{
+ device_t dev;
+
+ if (!have_addr)
+ return;
+
+ dev = (device_t)addr;
+
+ db_printf("name: %s\n", device_get_nameunit(dev));
+ db_printf(" driver: %s\n", DRIVERNAME(dev->driver));
+ db_printf(" class: %s\n", DEVCLANAME(dev->devclass));
+ db_printf(" addr: %p\n", dev);
+ db_printf(" parent: %p\n", dev->parent);
+ db_printf(" softc: %p\n", dev->softc);
+ db_printf(" ivars: %p\n", dev->ivars);
+}
+
+DB_SHOW_ALL_COMMAND(devices, db_show_all_devices)
+{
+ device_t dev;
+
+ TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
+ db_show_device((db_expr_t)dev, true, count, modif);
+ }
+}
+#endif
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index a04569e2eea1..488650190a3f 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -2242,10 +2242,10 @@ sys_kmq_setattr(struct thread *td, struct kmq_setattr_args *uap)
}
error = kern_kmq_setattr(td, uap->mqd, uap->attr != NULL ? &attr : NULL,
&oattr);
- if (error != 0)
- return (error);
- if (uap->oattr != NULL)
+ if (error == 0 && uap->oattr != NULL) {
+ bzero(oattr.__reserved, sizeof(oattr.__reserved));
error = copyout(&oattr, uap->oattr, sizeof(oattr));
+ }
return (error);
}
@@ -2759,10 +2759,9 @@ freebsd32_kmq_setattr(struct thread *td, struct freebsd32_kmq_setattr_args *uap)
}
error = kern_kmq_setattr(td, uap->mqd, uap->attr != NULL ? &attr : NULL,
&oattr);
- if (error != 0)
- return (error);
- if (uap->oattr != NULL) {
+ if (error == 0 && uap->oattr != NULL) {
mq_attr_to32(&oattr, &oattr32);
+ bzero(oattr32.__reserved, sizeof(oattr32.__reserved));
error = copyout(&oattr32, uap->oattr, sizeof(oattr32));
}
return (error);
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index be922edf0b0b..febba784835c 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -455,12 +455,9 @@ retry:
VM_WAIT;
VM_OBJECT_WLOCK(object);
goto retry;
- } else if (m->valid != VM_PAGE_BITS_ALL)
- rv = vm_pager_get_pages(object, &m, 1,
- NULL, NULL);
- else
- /* A cached page was reactivated. */
- rv = VM_PAGER_OK;
+ }
+ rv = vm_pager_get_pages(object, &m, 1, NULL,
+ NULL);
vm_page_lock(m);
if (rv == VM_PAGER_OK) {
vm_page_deactivate(m);
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 54f32c99d276..8d3d839d99e6 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -4655,7 +4655,24 @@ bdata2bio(struct buf *bp, struct bio *bip)
}
}
-static int buf_pager_relbuf;
+/*
+ * The MIPS pmap code currently doesn't handle aliased pages.
+ * The VIPT caches may not handle page aliasing themselves, leading
+ * to data corruption.
+ *
+ * As such, this code makes a system extremely unhappy if said
+ * system doesn't support unaliasing the above situation in hardware.
+ * Some "recent" systems (eg some mips24k/mips74k cores) don't enable
+ * this feature at build time, so it has to be handled in software.
+ *
+ * Once the MIPS pmap/cache code grows to support this function on
+ * earlier chips, it should be flipped back off.
+ */
+#ifdef __mips__
+static int buf_pager_relbuf = 1;
+#else
+static int buf_pager_relbuf = 0;
+#endif
SYSCTL_INT(_vfs, OID_AUTO, buf_pager_relbuf, CTLFLAG_RWTUN,
&buf_pager_relbuf, 0,
"Make buffer pager release buffers after reading");
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index bcfa50012190..bdde50222e63 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -783,7 +783,7 @@ cache_negative_shrink_select(int start, struct namecache **ncpp,
static void
cache_negative_zap_one(void)
{
- struct namecache *ncp, *ncp2, *ncpc;
+ struct namecache *ncp, *ncp2;
struct neglist *neglist;
struct mtx *dvlp;
struct rwlock *blp;
@@ -791,7 +791,6 @@ cache_negative_zap_one(void)
if (!mtx_trylock(&ncneg_shrink_lock))
return;
- ncpc = NULL;
mtx_lock(&ncneg_hot.nl_lock);
ncp = TAILQ_FIRST(&ncneg_hot.nl_list);
if (ncp != NULL) {
@@ -868,6 +867,13 @@ cache_zap_locked(struct namecache *ncp, bool neg_locked)
nc_get_name(ncp), ncp->nc_neghits);
}
LIST_REMOVE(ncp, nc_hash);
+ if (!(ncp->nc_flag & NCF_NEGATIVE)) {
+ TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst);
+ if (ncp == ncp->nc_vp->v_cache_dd)
+ ncp->nc_vp->v_cache_dd = NULL;
+ } else {
+ cache_negative_remove(ncp, neg_locked);
+ }
if (ncp->nc_flag & NCF_ISDOTDOT) {
if (ncp == ncp->nc_dvp->v_cache_dd)
ncp->nc_dvp->v_cache_dd = NULL;
@@ -878,13 +884,6 @@ cache_zap_locked(struct namecache *ncp, bool neg_locked)
atomic_subtract_rel_long(&numcachehv, 1);
}
}
- if (!(ncp->nc_flag & NCF_NEGATIVE)) {
- TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst);
- if (ncp == ncp->nc_vp->v_cache_dd)
- ncp->nc_vp->v_cache_dd = NULL;
- } else {
- cache_negative_remove(ncp, neg_locked);
- }
atomic_subtract_rel_long(&numcache, 1);
}
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 988c687bda7c..77a353b3cadb 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -61,8 +61,10 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_NETADDR, "export_host", "Export host address structure");
+#if defined(INET) || defined(INET6)
static struct radix_node_head *vfs_create_addrlist_af(
struct radix_node_head **prnh, int off);
+#endif
static void vfs_free_addrlist(struct netexport *nep);
static int vfs_free_netcred(struct radix_node *rn, void *w);
static void vfs_free_addrlist_af(struct radix_node_head **prnh);
@@ -239,6 +241,7 @@ vfs_free_netcred(struct radix_node *rn, void *w)
return (0);
}
+#if defined(INET) || defined(INET6)
static struct radix_node_head *
vfs_create_addrlist_af(struct radix_node_head **prnh, int off)
{
@@ -248,6 +251,7 @@ vfs_create_addrlist_af(struct radix_node_head **prnh, int off)
RADIX_NODE_HEAD_LOCK_INIT(*prnh);
return (*prnh);
}
+#endif
static void
vfs_free_addrlist_af(struct radix_node_head **prnh)
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index da8b824f6c3f..99bfb101f135 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -940,6 +940,11 @@ vfs_domount_update(
VOP_UNLOCK(vp, 0);
MNT_ILOCK(mp);
+ if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0) {
+ MNT_IUNLOCK(mp);
+ error = EBUSY;
+ goto end;
+ }
mp->mnt_flag &= ~MNT_UPDATEMASK;
mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE |
MNT_SNAPSHOT | MNT_ROOTFS | MNT_UPDATEMASK | MNT_RDONLY);
@@ -1235,6 +1240,24 @@ vfs_check_usecounts(struct mount *mp)
return (0);
}
+static void
+dounmount_cleanup(struct mount *mp, struct vnode *coveredvp, int mntkflags)
+{
+
+ mtx_assert(MNT_MTX(mp), MA_OWNED);
+ mp->mnt_kern_flag &= ~mntkflags;
+ if ((mp->mnt_kern_flag & MNTK_MWAIT) != 0) {
+ mp->mnt_kern_flag &= ~MNTK_MWAIT;
+ wakeup(mp);
+ }
+ MNT_IUNLOCK(mp);
+ if (coveredvp != NULL) {
+ VOP_UNLOCK(coveredvp, 0);
+ vdrop(coveredvp);
+ }
+ vn_finished_write(mp);
+}
+
/*
* Do the actual filesystem unmount.
*/
@@ -1281,13 +1304,9 @@ dounmount(struct mount *mp, int flags, struct thread *td)
vn_start_write(NULL, &mp, V_WAIT | V_MNTREF);
MNT_ILOCK(mp);
if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0 ||
+ (mp->mnt_flag & MNT_UPDATE) != 0 ||
!TAILQ_EMPTY(&mp->mnt_uppers)) {
- MNT_IUNLOCK(mp);
- if (coveredvp != NULL) {
- VOP_UNLOCK(coveredvp, 0);
- vdrop(coveredvp);
- }
- vn_finished_write(mp);
+ dounmount_cleanup(mp, coveredvp, 0);
return (EBUSY);
}
mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ;
@@ -1296,17 +1315,8 @@ dounmount(struct mount *mp, int flags, struct thread *td)
error = vfs_check_usecounts(mp);
MNT_ILOCK(mp);
if (error != 0) {
- mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_NOINSMNTQ);
- if (mp->mnt_kern_flag & MNTK_MWAIT) {
- mp->mnt_kern_flag &= ~MNTK_MWAIT;
- wakeup(mp);
- }
- MNT_IUNLOCK(mp);
- if (coveredvp != NULL) {
- VOP_UNLOCK(coveredvp, 0);
- vdrop(coveredvp);
- }
- vn_finished_write(mp);
+ dounmount_cleanup(mp, coveredvp, MNTK_UNMOUNT |
+ MNTK_NOINSMNTQ);
return (error);
}
}
diff --git a/sys/mips/atheros/ar531x/files.ar5315 b/sys/mips/atheros/ar531x/files.ar5315
index 7bb2dfa7a7ba..f608aa69de1c 100644
--- a/sys/mips/atheros/ar531x/files.ar5315
+++ b/sys/mips/atheros/ar531x/files.ar5315
@@ -14,17 +14,18 @@ mips/atheros/ar531x/uart_cpu_ar5315.c optional uart_ar5315
mips/atheros/ar531x/ar5312_chip.c standard
mips/atheros/ar71xx_bus_space_reversed.c standard
-#mips/mips/intr_machdep.c standard
mips/mips/tick.c standard
dev/etherswitch/e6000sw/e6060sw.c optional etherswitch
-dev/etherswitch/realtek/rtl830x.c optional etherswitch
# Hack to reuse ARM intrng code
-kern/subr_intr.c standard
-kern/msi_if.m standard
-kern/pic_if.m standard
+kern/subr_intr.c optional intrng
+kern/msi_if.m optional intrng
+kern/pic_if.m optional intrng
# Intrng compatible MIPS32 interrupt controller
-mips/mips/mips_pic.c standard
+mips/mips/mips_pic.c optional intrng
+
+# Non Intrng
+mips/mips/intr_machdep.c optional !intrng
diff --git a/sys/mips/atheros/ar531x/if_are.c b/sys/mips/atheros/ar531x/if_are.c
index d7bf6cbea84b..294961825f70 100644
--- a/sys/mips/atheros/ar531x/if_are.c
+++ b/sys/mips/atheros/ar531x/if_are.c
@@ -35,7 +35,7 @@
__FBSDID("$FreeBSD$");
/*
- * AR231x Ethernet interface driver
+ * AR531x Ethernet interface driver
* copy from mips/idt/if_kr.c and netbsd code
*/
#include <sys/param.h>
@@ -90,8 +90,6 @@ MODULE_DEPEND(are, miibus, 1, 1, 1);
#include <mips/atheros/ar531x/ar5315_setup.h>
#include <mips/atheros/ar531x/if_arereg.h>
-//#define ARE_DEBUG
-
#ifdef ARE_DEBUG
void dump_txdesc(struct are_softc *, int);
void dump_status_reg(struct are_softc *);
@@ -226,7 +224,7 @@ are_attach(device_t dev)
unit = device_get_unit(dev);
sc->are_dev = dev;
- // hardcode macaddress
+ /* hardcode macaddress */
sc->are_eaddr[0] = 0x00;
sc->are_eaddr[1] = 0x0C;
sc->are_eaddr[2] = 0x42;
@@ -234,7 +232,7 @@ are_attach(device_t dev)
sc->are_eaddr[4] = 0x5E;
sc->are_eaddr[5] = 0x6B;
- // try to get from hints
+ /* try to get from hints */
if (!resource_string_value(device_get_name(dev),
device_get_unit(dev), "macaddr", (const char **)&local_macstr)) {
uint32_t tmpmac[ETHER_ADDR_LEN];
@@ -302,12 +300,16 @@ are_attach(device_t dev)
ifp->if_ioctl = are_ioctl;
ifp->if_start = are_start;
ifp->if_init = are_init;
+ sc->are_if_flags = ifp->if_flags;
/* XXX: add real size */
IFQ_SET_MAXLEN(&ifp->if_snd, 9);
ifp->if_snd.ifq_maxlen = 9;
IFQ_SET_READY(&ifp->if_snd);
+ /* Tell the upper layer(s) we support long frames. */
+ ifp->if_capabilities |= IFCAP_VLAN_MTU;
+
ifp->if_capenable = ifp->if_capabilities;
if (are_dma_alloc(sc) != 0) {
@@ -315,14 +317,6 @@ are_attach(device_t dev)
goto fail;
}
- /* TODO: calculate prescale */
-/*
- CSR_WRITE_4(sc, ARE_ETHMCP, (165000000 / (1250000 + 1)) & ~1);
-
- CSR_WRITE_4(sc, ARE_MIIMCFG, ARE_MIIMCFG_R);
- DELAY(1000);
- CSR_WRITE_4(sc, ARE_MIIMCFG, 0);
-*/
CSR_WRITE_4(sc, CSR_BUSMODE, BUSMODE_SWR);
DELAY(1000);
@@ -350,11 +344,11 @@ are_attach(device_t dev)
#ifdef INTRNG
char *name;
- if(ar531x_soc >= AR531X_SOC_AR5315) {
+ if (ar531x_soc >= AR531X_SOC_AR5315) {
enetirq = AR5315_CPU_IRQ_ENET;
name = "enet";
} else {
- if(device_get_unit(dev) == 0) {
+ if (device_get_unit(dev) == 0) {
enetirq = AR5312_IRQ_ENET0;
name = "enet0";
} else {
@@ -465,7 +459,6 @@ are_miibus_readreg(device_t dev, int phy, int reg)
addr = (phy << MIIADDR_PHY_SHIFT) | (reg << MIIADDR_REG_SHIFT);
CSR_WRITE_4(sc, CSR_MIIADDR, addr);
-// AE_BARRIER(sc);
for (i = 0; i < 100000000; i++) {
if ((CSR_READ_4(sc, CSR_MIIADDR) & MIIADDR_BUSY) == 0)
break;
@@ -488,7 +481,6 @@ are_miibus_writereg(device_t dev, int phy, int reg, int data)
addr = (phy << MIIADDR_PHY_SHIFT) | (reg << MIIADDR_REG_SHIFT) |
MIIADDR_WRITE;
CSR_WRITE_4(sc, CSR_MIIADDR, addr);
-// AE_BARRIER(sc);
for (i = 0; i < 100000000; i++) {
if ((CSR_READ_4(sc, CSR_MIIADDR) & MIIADDR_BUSY) == 0)
@@ -610,7 +602,6 @@ are_init_locked(struct are_softc *sc)
*/
CSR_WRITE_4(sc, CSR_BUSMODE,
/* XXX: not sure if this is a good thing or not... */
- //BUSMODE_ALIGN_16B |
BUSMODE_BAR | BUSMODE_BLE | BUSMODE_PBL_4LW);
/*
@@ -648,15 +639,16 @@ are_init_locked(struct are_softc *sc)
/*
* Start the mac.
*/
- CSR_WRITE_4(sc, CSR_MACCTL, CSR_READ_4(sc, CSR_MACCTL) |
- (MACCTL_RE | MACCTL_TE));
+ CSR_WRITE_4(sc, CSR_FLOWC, FLOWC_FCE);
+ CSR_WRITE_4(sc, CSR_MACCTL, MACCTL_RE | MACCTL_TE |
+ MACCTL_PM | MACCTL_FDX | MACCTL_HBD | MACCTL_RA);
/*
* Write out the opmode.
*/
- CSR_WRITE_4(sc, CSR_OPMODE, OPMODE_SR | OPMODE_ST |
-// ae_txthresh[sc->sc_txthresh].txth_opmode);
+ CSR_WRITE_4(sc, CSR_OPMODE, OPMODE_SR | OPMODE_ST | OPMODE_SF |
OPMODE_TR_64);
+
/*
* Start the receive process.
*/
@@ -741,7 +733,6 @@ are_encap(struct are_softc *sc, struct mbuf **m_head)
if (i == 0)
desc->are_devcs |= ADCTL_Tx_FS;
desc->are_addr = txsegs[i].ds_addr;
-// desc->are_link = 0;
/* link with previous descriptor */
if (prev_desc)
prev_desc->are_link = ARE_TX_RING_ADDR(sc, prod);
@@ -850,6 +841,36 @@ are_stop(struct are_softc *sc)
}
+static int
+are_set_filter(struct are_softc *sc)
+{
+ struct ifnet *ifp;
+ int mchash[2];
+ int macctl;
+
+ ifp = sc->are_ifp;
+
+ macctl = CSR_READ_4(sc, CSR_MACCTL);
+ macctl &= ~(MACCTL_PR | MACCTL_PM);
+ macctl |= MACCTL_HBD;
+
+ if (ifp->if_flags & IFF_PROMISC)
+ macctl |= MACCTL_PR;
+
+ /* Todo: hash table set.
+ * But I don't know how to use multicast hash table at this soc.
+ */
+
+ /* this is allmulti */
+ mchash[0] = mchash[1] = 0xffffffff;
+ macctl |= MACCTL_PM;
+
+ CSR_WRITE_4(sc, CSR_HTLO, mchash[0]);
+ CSR_WRITE_4(sc, CSR_HTHI, mchash[1]);
+ CSR_WRITE_4(sc, CSR_MACCTL, macctl);
+
+ return 0;
+}
static int
are_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
@@ -863,7 +884,6 @@ are_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
switch (command) {
case SIOCSIFFLAGS:
-#if 0
ARE_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
@@ -880,16 +900,13 @@ are_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
sc->are_if_flags = ifp->if_flags;
ARE_UNLOCK(sc);
-#endif
error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
-#if 0
ARE_LOCK(sc);
are_set_filter(sc);
ARE_UNLOCK(sc);
-#endif
error = 0;
break;
case SIOCGIFMEDIA:
@@ -903,28 +920,6 @@ are_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
break;
case SIOCSIFCAP:
error = 0;
-#if 0
- mask = ifr->ifr_reqcap ^ ifp->if_capenable;
- if ((mask & IFCAP_HWCSUM) != 0) {
- ifp->if_capenable ^= IFCAP_HWCSUM;
- if ((IFCAP_HWCSUM & ifp->if_capenable) &&
- (IFCAP_HWCSUM & ifp->if_capabilities))
- ifp->if_hwassist = ARE_CSUM_FEATURES;
- else
- ifp->if_hwassist = 0;
- }
- if ((mask & IFCAP_VLAN_HWTAGGING) != 0) {
- ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
- if (IFCAP_VLAN_HWTAGGING & ifp->if_capenable &&
- IFCAP_VLAN_HWTAGGING & ifp->if_capabilities &&
- ifp->if_drv_flags & IFF_DRV_RUNNING) {
- ARE_LOCK(sc);
- are_vlan_setup(sc);
- ARE_UNLOCK(sc);
- }
- }
- VLAN_CAPABILITIES(ifp);
-#endif
break;
default:
error = ether_ioctl(ifp, command, data);
@@ -1343,7 +1338,7 @@ are_newbuf(struct are_softc *sc, int idx)
return (ENOBUFS);
m->m_len = m->m_pkthdr.len = MCLBYTES;
- // tcp header boundary margin
+ /* tcp header boundary margin */
m_adj(m, 4);
if (bus_dmamap_load_mbuf_sg(sc->are_cdata.are_rx_tag,
@@ -1355,9 +1350,11 @@ are_newbuf(struct are_softc *sc, int idx)
rxd = &sc->are_cdata.are_rxdesc[idx];
if (rxd->rx_m != NULL) {
-// This code make bug. Make scranble on buffer data.
-// bus_dmamap_sync(sc->are_cdata.are_rx_tag, rxd->rx_dmamap,
-// BUS_DMASYNC_POSTREAD);
+ /*
+ * THis is if_kr.c original code but make bug. Make scranble on buffer data.
+ * bus_dmamap_sync(sc->are_cdata.are_rx_tag, rxd->rx_dmamap,
+ * BUS_DMASYNC_POSTREAD);
+ */
bus_dmamap_unload(sc->are_cdata.are_rx_tag, rxd->rx_dmamap);
}
map = rxd->rx_dmamap;
@@ -1551,7 +1548,6 @@ are_intr(void *arg)
struct are_softc *sc = arg;
uint32_t status;
struct ifnet *ifp = sc->are_ifp;
-//kdb_break();
ARE_LOCK(sc);
diff --git a/sys/mips/atheros/ar531x/if_arereg.h b/sys/mips/atheros/ar531x/if_arereg.h
index 19aad0ce3948..f59df630d9ee 100644
--- a/sys/mips/atheros/ar531x/if_arereg.h
+++ b/sys/mips/atheros/ar531x/if_arereg.h
@@ -37,17 +37,17 @@ struct are_desc {
uint32_t are_link;
};
-#define ARE_DMASIZE(len) ((len) & ((1 << 11)-1))
-#define ARE_PKTSIZE(len) ((len & 0xffff0000) >> 16)
-
-#define ARE_RX_RING_CNT 128
-#define ARE_TX_RING_CNT 128
-#define ARE_TX_RING_SIZE sizeof(struct are_desc) * ARE_TX_RING_CNT
-#define ARE_RX_RING_SIZE sizeof(struct are_desc) * ARE_RX_RING_CNT
-#define ARE_RING_ALIGN sizeof(struct are_desc)
-#define ARE_RX_ALIGN sizeof(uint32_t)
-#define ARE_MAXFRAGS 8
-#define ARE_TX_INTR_THRESH 8
+#define ARE_DMASIZE(len) ((len) & ((1 << 11)-1))
+#define ARE_PKTSIZE(len) ((len & 0xffff0000) >> 16)
+
+#define ARE_RX_RING_CNT 128
+#define ARE_TX_RING_CNT 128
+#define ARE_TX_RING_SIZE sizeof(struct are_desc) * ARE_TX_RING_CNT
+#define ARE_RX_RING_SIZE sizeof(struct are_desc) * ARE_RX_RING_CNT
+#define ARE_RING_ALIGN sizeof(struct are_desc)
+#define ARE_RX_ALIGN sizeof(uint32_t)
+#define ARE_MAXFRAGS 8
+#define ARE_TX_INTR_THRESH 8
#define ARE_TX_RING_ADDR(sc, i) \
((sc)->are_rdata.are_tx_ring_paddr + sizeof(struct are_desc) * (i))
@@ -123,6 +123,7 @@ struct are_softc {
struct are_ring_data are_rdata;
int are_link_status;
int are_detach;
+ int are_if_flags; /* last if flags */
};
#define ARE_LOCK(_sc) mtx_lock(&(_sc)->are_mtx)
@@ -132,11 +133,11 @@ struct are_softc {
/*
* register space access macros
*/
-#define CSR_WRITE_4(sc, reg, val) \
- bus_space_write_4(sc->are_btag, sc->are_bhandle, reg, val)
+#define CSR_WRITE_4(sc, reg, val) \
+ bus_space_write_4(sc->are_btag, sc->are_bhandle, reg, val)
-#define CSR_READ_4(sc, reg) \
- bus_space_read_4(sc->are_btag, sc->are_bhandle, reg)
+#define CSR_READ_4(sc, reg) \
+ bus_space_read_4(sc->are_btag, sc->are_bhandle, reg)
/* $NetBSD: aereg.h,v 1.2 2008/04/28 20:23:28 martin Exp $ */
diff --git a/sys/mips/include/cpufunc.h b/sys/mips/include/cpufunc.h
index 427aba74cd3a..5ebaf4cc1720 100644
--- a/sys/mips/include/cpufunc.h
+++ b/sys/mips/include/cpufunc.h
@@ -249,7 +249,8 @@ MIPS_RW32_COP0_SEL(config5, MIPS_COP_0_CONFIG, 5);
#if defined(CPU_NLM) || defined(BERI_LARGE_TLB)
MIPS_RW32_COP0_SEL(config6, MIPS_COP_0_CONFIG, 6);
#endif
-#if defined(CPU_NLM) || defined(CPU_MIPS1004K)
+#if defined(CPU_NLM) || defined(CPU_MIPS1004K) || defined (CPU_MIPS74K) || \
+ defined(CPU_MIPS24K)
MIPS_RW32_COP0_SEL(config7, MIPS_COP_0_CONFIG, 7);
#endif
MIPS_RW32_COP0(count, MIPS_COP_0_COUNT);
@@ -278,6 +279,13 @@ MIPS_RW32_COP0(entrylo1, MIPS_COP_0_TLB_LO1);
MIPS_RW32_COP0(prid, MIPS_COP_0_PRID);
/* XXX 64-bit? */
MIPS_RW32_COP0_SEL(ebase, MIPS_COP_0_PRID, 1);
+#ifdef CPU_XBURST
+MIPS_RW32_COP0_SEL(xburst_mbox0, MIPS_COP_0_XBURST_MBOX, 0);
+MIPS_RW32_COP0_SEL(xburst_mbox1, MIPS_COP_0_XBURST_MBOX, 1);
+MIPS_RW32_COP0_SEL(xburst_core_ctl, MIPS_COP_0_XBURST_C12, 2);
+MIPS_RW32_COP0_SEL(xburst_core_sts, MIPS_COP_0_XBURST_C12, 3);
+MIPS_RW32_COP0_SEL(xburst_reim, MIPS_COP_0_XBURST_C12, 4);
+#endif
MIPS_RW32_COP0(watchlo, MIPS_COP_0_WATCH_LO);
MIPS_RW32_COP0_SEL(watchlo1, MIPS_COP_0_WATCH_LO, 1);
MIPS_RW32_COP0_SEL(watchlo2, MIPS_COP_0_WATCH_LO, 2);
diff --git a/sys/mips/include/cpuregs.h b/sys/mips/include/cpuregs.h
index 4ce7e1b4fb2a..26bee195e648 100644
--- a/sys/mips/include/cpuregs.h
+++ b/sys/mips/include/cpuregs.h
@@ -522,12 +522,18 @@
#define MIPS_COP_0_COUNT _(9)
#define MIPS_COP_0_COMPARE _(11)
-
+#ifdef CPU_XBURST
+#define MIPS_COP_0_XBURST_C12 _(12)
+#endif
#define MIPS_COP_0_CONFIG _(16)
#define MIPS_COP_0_LLADDR _(17)
#define MIPS_COP_0_WATCH_LO _(18)
#define MIPS_COP_0_WATCH_HI _(19)
#define MIPS_COP_0_TLB_XCONTEXT _(20)
+#ifdef CPU_XBURST
+#define MIPS_COP_0_XBURST_MBOX _(20)
+#endif
+
#define MIPS_COP_0_ECC _(26)
#define MIPS_COP_0_CACHE_ERR _(27)
#define MIPS_COP_0_TAG_LO _(28)
diff --git a/sys/mips/include/locore.h b/sys/mips/include/locore.h
index 1e4092e2318e..1f101a5175fc 100644
--- a/sys/mips/include/locore.h
+++ b/sys/mips/include/locore.h
@@ -59,6 +59,9 @@
#define MIPS_PRID_CID_LEXRA 0x0b /* Lexra */
#define MIPS_PRID_CID_RMI 0x0c /* RMI */
#define MIPS_PRID_CID_CAVIUM 0x0d /* Cavium */
+#define MIPS_PRID_CID_INGENIC 0xe1 /* Ingenic */
+#define MIPS_PRID_CID_INGENIC2 0xd1 /* Ingenic */
+
#define MIPS_PRID_COPTS(x) (((x) >> 24) & 0x00ff) /* Company Options */
#endif /* _MIPS_LOCORE_H */
diff --git a/sys/mips/include/param.h b/sys/mips/include/param.h
index 7c5e667858fe..37e1fd344f7d 100644
--- a/sys/mips/include/param.h
+++ b/sys/mips/include/param.h
@@ -53,33 +53,36 @@
#define __PCI_REROUTE_INTERRUPT
-#ifndef MACHINE
-#define MACHINE "mips"
-#endif
-#ifndef MACHINE_ARCH
#if _BYTE_ORDER == _BIG_ENDIAN
-#ifdef __mips_n64
-#define MACHINE_ARCH "mips64"
-#ifndef MACHINE_ARCH32
-#define MACHINE_ARCH32 "mips"
+# define _EL_SUFFIX ""
+#else
+# define _EL_SUFFIX "el"
#endif
+
+#ifdef __mips_n64
+# define _N64_SUFFIX "64"
#elif defined(__mips_n32)
-#define MACHINE_ARCH "mipsn32"
+# define _N64_SUFFIX "n32"
#else
-#define MACHINE_ARCH "mips"
+# define _N64_SUFFIX ""
#endif
+
+#ifdef __mips_hard_float
+# define _HF_SUFFIX "hf"
#else
-#ifdef __mips_n64
-#define MACHINE_ARCH "mips64el"
-#ifndef MACHINE_ARCH32
-#define MACHINE_ARCH32 "mipsel"
+# define _HF_SUFFIX ""
#endif
-#elif defined(__mips_n32)
-#define MACHINE_ARCH "mipsn32el"
-#else
-#define MACHINE_ARCH "mipsel"
+
+#ifndef MACHINE
+# define MACHINE "mips"
#endif
+#ifndef MACHINE_ARCH
+# define MACHINE_ARCH "mips" _N64_SUFFIX _EL_SUFFIX _HF_SUFFIX
#endif
+#ifdef __mips_n64
+# ifndef MACHINE_ARCH32
+# define MACHINE_ARCH32 "mips" _EL_SUFFIX _HF_SUFFIX
+# endif
#endif
/*
diff --git a/sys/mips/mediatek/mtk_soc.c b/sys/mips/mediatek/mtk_soc.c
index ff40abfd1eb6..62e01c805633 100644
--- a/sys/mips/mediatek/mtk_soc.c
+++ b/sys/mips/mediatek/mtk_soc.c
@@ -248,7 +248,7 @@ mtk_soc_try_early_detect(void)
return;
for (i = 0; compat_data[i].ocd_str != NULL; i++) {
- if (fdt_is_compatible(node, compat_data[i].ocd_str)) {
+ if (ofw_bus_node_is_compatible(node, compat_data[i].ocd_str)) {
mtk_soc_socid = compat_data[i].ocd_data;
break;
}
diff --git a/sys/mips/mips/cpu.c b/sys/mips/mips/cpu.c
index e8f48dcb8f88..fa68fd32e743 100644
--- a/sys/mips/mips/cpu.c
+++ b/sys/mips/mips/cpu.c
@@ -337,6 +337,9 @@ static void
cpu_identify(void)
{
uint32_t cfg0, cfg1, cfg2, cfg3;
+#if defined(CPU_MIPS1004K) || defined (CPU_MIPS74K) || defined (CPU_MIPS24K)
+ uint32_t cfg7;
+#endif
printf("cpu%d: ", 0); /* XXX per-cpu */
switch (cpuinfo.cpu_vendor) {
case MIPS_PRID_CID_MTI:
@@ -370,6 +373,10 @@ cpu_identify(void)
case MIPS_PRID_CID_CAVIUM:
printf("Cavium");
break;
+ case MIPS_PRID_CID_INGENIC:
+ case MIPS_PRID_CID_INGENIC2:
+ printf("Ingenic XBurst");
+ break;
case MIPS_PRID_CID_PREHISTORIC:
default:
printf("Unknown cid %#x", cpuinfo.cpu_vendor);
@@ -478,7 +485,12 @@ cpu_identify(void)
/* Print Config3 if it contains any useful info */
if (cfg3 & ~(0x80000000))
- printf(" Config3=0x%b\n", cfg3, "\20\14ULRI\2SmartMIPS\1TraceLogic");
+ printf(" Config3=0x%b\n", cfg3, "\20\16ULRI\2SmartMIPS\1TraceLogic");
+
+#if defined(CPU_MIPS1004K) || defined (CPU_MIPS74K) || defined (CPU_MIPS24K)
+ cfg7 = mips_rd_config7();
+ printf(" Config7=0x%b\n", cfg7, "\20\40WII\21AR");
+#endif
}
static struct rman cpu_hardirq_rman;
diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c
index 2bc7787dc051..638c9cbc50f7 100644
--- a/sys/mips/mips/pmap.c
+++ b/sys/mips/mips/pmap.c
@@ -74,11 +74,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/rwlock.h>
#include <sys/sched.h>
-#ifdef SMP
#include <sys/smp.h>
-#else
-#include <sys/cpuset.h>
-#endif
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
@@ -3266,9 +3262,19 @@ pmap_activate(struct thread *td)
critical_exit();
}
+static void
+pmap_sync_icache_one(void *arg __unused)
+{
+
+ mips_icache_sync_all();
+ mips_dcache_wbinv_all();
+}
+
void
pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz)
{
+
+ smp_rendezvous(NULL, pmap_sync_icache_one, NULL, NULL);
}
/*
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index b5ac84dbabb3..602f3da52b3a 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -57,6 +57,7 @@ SUBDIR= \
${_bios} \
${_bktr} \
${_bm} \
+ bnxt \
bridgestp \
bwi \
bwn \
diff --git a/sys/modules/bnxt/Makefile b/sys/modules/bnxt/Makefile
new file mode 100644
index 000000000000..1d478d16671d
--- /dev/null
+++ b/sys/modules/bnxt/Makefile
@@ -0,0 +1,14 @@
+#$FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/bnxt
+
+KMOD = if_bnxt
+SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h ifdi_if.h
+SRCS += opt_inet.h opt_inet6.h opt_rss.h
+SRCS += bnxt_txrx.c if_bnxt.c
+SRCS += bnxt_hwrm.c bnxt_hwrm.h
+SRCS += bnxt_sysctl.c bnxt_sysctl.h
+
+CFLAGS+= -DIFLIB
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/dtrace/dtrace/Makefile b/sys/modules/dtrace/dtrace/Makefile
index 543be8c20191..0889646f88c0 100644
--- a/sys/modules/dtrace/dtrace/Makefile
+++ b/sys/modules/dtrace/dtrace/Makefile
@@ -60,7 +60,11 @@ assym.o: assym.s
.if ${MACHINE_CPUARCH} == "riscv"
assym.o: assym.s
+.if ${TARGET_ARCH:Mriscv*sf}
${AS} -mfloat-abi=soft -o assym.o assym.s
+.else
+ ${AS} -mfloat-abi=double -o assym.o assym.s
+.endif
.endif
.include <bsd.kmod.mk>
diff --git a/sys/modules/hyperv/pcib/Makefile b/sys/modules/hyperv/pcib/Makefile
new file mode 100644
index 000000000000..1b63a138dc1f
--- /dev/null
+++ b/sys/modules/hyperv/pcib/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/hyperv/pcib \
+ ${.CURDIR}/../../../dev/hyperv/vmbus
+
+KMOD= vmbus_pcib
+SRCS= vmbus_pcib.c
+SRCS+= bus_if.h device_if.h pci_if.h pcib_if.h vmbus_if.h
+
+CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/pcib
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/hyperv/utilities/Makefile b/sys/modules/hyperv/utilities/Makefile
index 290bd2737ad5..28125fd2867c 100644
--- a/sys/modules/hyperv/utilities/Makefile
+++ b/sys/modules/hyperv/utilities/Makefile
@@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../../../dev/hyperv/utilities
KMOD= hv_utils
-SRCS= hv_util.c hv_kvp.c hv_timesync.c hv_shutdown.c hv_heartbeat.c
+SRCS= hv_util.c hv_kvp.c hv_snapshot.c hv_timesync.c hv_shutdown.c hv_heartbeat.c hv_snapshot.c
SRCS+= bus_if.h device_if.h vmbus_if.h
CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/include \
diff --git a/sys/modules/hyperv/vmbus/Makefile b/sys/modules/hyperv/vmbus/Makefile
index 105b4f5b7515..d6052e51d754 100644
--- a/sys/modules/hyperv/vmbus/Makefile
+++ b/sys/modules/hyperv/vmbus/Makefile
@@ -13,7 +13,7 @@ SRCS= hyperv.c \
vmbus_et.c \
vmbus_if.c \
vmbus_xact.c
-SRCS+= acpi_if.h bus_if.h device_if.h opt_acpi.h vmbus_if.h
+SRCS+= acpi_if.h bus_if.h device_if.h opt_acpi.h pci_if.h pcib_if.h vmbus_if.h
# XXX: for assym.s
SRCS+= opt_kstack_pages.h opt_nfs.h opt_hwpmc_hooks.h opt_compat.h
diff --git a/sys/modules/kbdmux/Makefile b/sys/modules/kbdmux/Makefile
index 363343a87db1..03feb8fb8b5c 100644
--- a/sys/modules/kbdmux/Makefile
+++ b/sys/modules/kbdmux/Makefile
@@ -4,7 +4,8 @@
.PATH: ${.CURDIR}/../../dev/kbdmux
KMOD= kbdmux
-SRCS= kbdmux.c opt_compat.h opt_kbd.h opt_kbdmux.h bus_if.h device_if.h
+SRCS= kbdmux.c opt_compat.h opt_evdev.h opt_kbd.h opt_kbdmux.h bus_if.h \
+ device_if.h
.if !defined(KERNBUILDDIR)
opt_compat.h:
diff --git a/sys/modules/rpi_ft5406/Makefile b/sys/modules/rpi_ft5406/Makefile
index 2360ceda44a9..3a1bbf5762ac 100644
--- a/sys/modules/rpi_ft5406/Makefile
+++ b/sys/modules/rpi_ft5406/Makefile
@@ -5,6 +5,6 @@
KMOD= rpi_ft5406
SRCS= bcm2835_ft5406.c
-SRCS+= bus_if.h device_if.h ofw_bus_if.h
+SRCS+= bus_if.h device_if.h mbox_if.h ofw_bus_if.h
.include <bsd.kmod.mk>
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index 42f0d4ce93ec..25f5c741a883 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -93,7 +93,6 @@ __FBSDID("$FreeBSD$");
#include <x86/iommu/busdma_dmar.h>
#endif
-
/*
* enable accounting of every mbuf as it comes in to and goes out of iflib's software descriptor references
*/
@@ -500,7 +499,7 @@ static SYSCTL_NODE(_net, OID_AUTO, iflib, CTLFLAG_RD, 0,
static int iflib_min_tx_latency = 0;
SYSCTL_INT(_net_iflib, OID_AUTO, min_tx_latency, CTLFLAG_RW,
- &iflib_min_tx_latency, 0, "minimize transmit latency at the possibel expense of throughput");
+ &iflib_min_tx_latency, 0, "minimize transmit latency at the possible expense of throughput");
#if IFLIB_DEBUG_COUNTERS
@@ -595,10 +594,23 @@ SYSCTL_INT(_net_iflib, OID_AUTO, verbose_debug, CTLFLAG_RW,
&iflib_verbose_debug, 0, "enable verbose debugging");
#define DBG_COUNTER_INC(name) atomic_add_int(&(iflib_ ## name), 1)
+static void
+iflib_debug_reset(void)
+{
+ iflib_tx_seen = iflib_tx_sent = iflib_tx_encap = iflib_rx_allocs =
+ iflib_fl_refills = iflib_fl_refills_large = iflib_tx_frees =
+ iflib_txq_drain_flushing = iflib_txq_drain_oactive =
+ iflib_txq_drain_notready = iflib_txq_drain_encapfail =
+ iflib_encap_load_mbuf_fail = iflib_encap_txq_avail_fail =
+ iflib_encap_txd_encap_fail = iflib_task_fn_rxs = iflib_rx_intr_enables =
+ iflib_fast_intrs = iflib_intr_link = iflib_intr_msix = iflib_rx_unavail =
+ iflib_rx_ctx_inactive = iflib_rx_zero_len = iflib_rx_if_input =
+ iflib_rx_mbuf_null = iflib_rxd_flush = 0;
+}
#else
#define DBG_COUNTER_INC(name)
-
+static void iflib_debug_reset(void) {}
#endif
@@ -619,6 +631,7 @@ static int iflib_register(if_ctx_t);
static void iflib_init_locked(if_ctx_t ctx);
static void iflib_add_device_sysctl_pre(if_ctx_t ctx);
static void iflib_add_device_sysctl_post(if_ctx_t ctx);
+static void iflib_ifmp_purge(iflib_txq_t txq);
#ifdef DEV_NETMAP
@@ -1266,11 +1279,6 @@ iflib_txsd_alloc(iflib_txq_t txq)
sctx->isc_tx_maxsize, nsegments, sctx->isc_tx_maxsegsize);
goto fail;
}
-#ifdef IFLIB_DIAGNOSTICS
- device_printf(dev,"maxsize: %zd nsegments: %d maxsegsize: %zd\n",
- sctx->isc_tx_maxsize, nsegments, sctx->isc_tx_maxsegsize);
-
-#endif
if ((err = bus_dma_tag_create(bus_get_dma_tag(dev),
1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
@@ -1287,11 +1295,6 @@ iflib_txsd_alloc(iflib_txq_t txq)
goto fail;
}
-#ifdef IFLIB_DIAGNOSTICS
- device_printf(dev,"TSO maxsize: %d ntsosegments: %d maxsegsize: %d\n",
- scctx->isc_tx_tso_size_max, ntsosegments,
- scctx->isc_tx_tso_segsize_max);
-#endif
if (!(txq->ift_sds.ifsd_flags =
(uint8_t *) malloc(sizeof(uint8_t) *
scctx->isc_ntxd[txq->ift_br_offset], M_IFLIB, M_NOWAIT | M_ZERO))) {
@@ -1921,20 +1924,23 @@ iflib_stop(if_ctx_t ctx)
if_setdrvflagbits(ctx->ifc_ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING);
IFDI_INTR_DISABLE(ctx);
- msleep(ctx, &ctx->ifc_mtx, PUSER, "iflib_init", hz);
+ DELAY(100000);
+ IFDI_STOP(ctx);
+ DELAY(100000);
+ iflib_debug_reset();
/* Wait for current tx queue users to exit to disarm watchdog timer. */
for (i = 0; i < scctx->isc_ntxqsets; i++, txq++) {
/* make sure all transmitters have completed before proceeding XXX */
/* clean any enqueued buffers */
- iflib_txq_check_drain(txq, 0);
+ iflib_ifmp_purge(txq);
/* Free any existing tx buffers. */
for (j = 0; j < txq->ift_size; j++) {
iflib_txsd_free(ctx, txq, j);
}
txq->ift_processed = txq->ift_cleaned = txq->ift_cidx_processed = 0;
- txq->ift_in_use = txq->ift_cidx = txq->ift_pidx = txq->ift_no_desc_avail = 0;
+ txq->ift_in_use = txq->ift_gen = txq->ift_cidx = txq->ift_pidx = txq->ift_no_desc_avail = 0;
txq->ift_closed = txq->ift_mbuf_defrag = txq->ift_mbuf_defrag_failed = 0;
txq->ift_no_tx_dma_setup = txq->ift_txd_encap_efbig = txq->ift_map_failed = 0;
txq->ift_pullups = 0;
@@ -1951,7 +1957,6 @@ iflib_stop(if_ctx_t ctx)
for (j = 0, fl = rxq->ifr_fl; j < rxq->ifr_nfl; j++, fl++)
iflib_fl_bufs_free(fl);
}
- IFDI_STOP(ctx);
}
static iflib_rxsd_t
@@ -2890,22 +2895,27 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx)
}
consumed = mcast_sent = bytes_sent = pkt_sent = 0;
count = MIN(avail, TX_BATCH_SIZE);
+#ifdef INVARIANTS
+ if (iflib_verbose_debug)
+ printf("%s avail=%d ifc_flags=%x txq_avail=%d ", __FUNCTION__,
+ avail, ctx->ifc_flags, TXQ_AVAIL(txq));
+#endif
for (desc_used = i = 0; i < count && TXQ_AVAIL(txq) > MAX_TX_DESC(ctx) + 2; i++) {
mp = _ring_peek_one(r, cidx, i);
+ MPASS(mp != NULL && *mp != NULL);
in_use_prev = txq->ift_in_use;
- err = iflib_encap(txq, mp);
- /*
- * What other errors should we bail out for?
- */
- if (err == ENOBUFS) {
+ if ((err = iflib_encap(txq, mp)) == ENOBUFS) {
DBG_COUNTER_INC(txq_drain_encapfail);
+ /* no room - bail out */
break;
}
consumed++;
- if (err)
+ if (err) {
+ DBG_COUNTER_INC(txq_drain_encapfail);
+ /* we can't send this packet - skip it */
continue;
-
+ }
pkt_sent++;
m = *mp;
DBG_COUNTER_INC(tx_sent);
@@ -2936,10 +2946,58 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx)
if_inc_counter(ifp, IFCOUNTER_OPACKETS, pkt_sent);
if (mcast_sent)
if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast_sent);
-
+#ifdef INVARIANTS
+ if (iflib_verbose_debug)
+ printf("consumed=%d\n", consumed);
+#endif
return (consumed);
}
+static uint32_t
+iflib_txq_drain_always(struct ifmp_ring *r)
+{
+ return (1);
+}
+
+static uint32_t
+iflib_txq_drain_free(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx)
+{
+ int i, avail;
+ struct mbuf **mp;
+ iflib_txq_t txq;
+
+ txq = r->cookie;
+
+ txq->ift_qstatus = IFLIB_QUEUE_IDLE;
+ CALLOUT_LOCK(txq);
+ callout_stop(&txq->ift_timer);
+ callout_stop(&txq->ift_db_check);
+ CALLOUT_UNLOCK(txq);
+
+ avail = IDXDIFF(pidx, cidx, r->size);
+ for (i = 0; i < avail; i++) {
+ mp = _ring_peek_one(r, cidx, i);
+ m_freem(*mp);
+ }
+ MPASS(ifmp_ring_is_stalled(r) == 0);
+ return (avail);
+}
+
+static void
+iflib_ifmp_purge(iflib_txq_t txq)
+{
+ struct ifmp_ring *r;
+
+ r = txq->ift_br[0];
+ r->drain = iflib_txq_drain_free;
+ r->can_drain = iflib_txq_drain_always;
+
+ ifmp_ring_check_drainage(r, r->size);
+
+ r->drain = iflib_txq_drain;
+ r->can_drain = iflib_txq_can_drain;
+}
+
static void
_task_fn_tx(void *context)
{
@@ -3073,7 +3131,7 @@ iflib_if_transmit(if_t ifp, struct mbuf *m)
if (__predict_false((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || !LINK_ACTIVE(ctx))) {
DBG_COUNTER_INC(tx_frees);
m_freem(m);
- return (0);
+ return (ENOBUFS);
}
MPASS(m->m_nextpkt == NULL);
@@ -3590,6 +3648,10 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct
if (scctx->isc_rss_table_size == 0)
scctx->isc_rss_table_size = 64;
scctx->isc_rss_table_mask = scctx->isc_rss_table_size-1;
+
+ GROUPTASK_INIT(&ctx->ifc_admin_task, 0, _task_fn_admin, ctx);
+ /* XXX format name */
+ taskqgroup_attach(qgroup_if_config_tqg, &ctx->ifc_admin_task, ctx, -1, "admin");
/*
** Now setup MSI or MSI/X, should
** return us the number of supported
@@ -4342,6 +4404,7 @@ iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid,
gtask = &ctx->ifc_txqs[qid].ift_task;
tqg = qgroup_if_io_tqg;
fn = _task_fn_tx;
+ GROUPTASK_INIT(gtask, 0, fn, q);
break;
case IFLIB_INTR_RX:
q = &ctx->ifc_rxqs[qid];
@@ -4349,9 +4412,11 @@ iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid,
gtask = &ctx->ifc_rxqs[qid].ifr_task;
tqg = qgroup_if_io_tqg;
fn = _task_fn_rx;
+ GROUPTASK_INIT(gtask, 0, fn, q);
break;
case IFLIB_INTR_ADMIN:
q = ctx;
+ tqrid = -1;
info = &ctx->ifc_filter_info;
gtask = &ctx->ifc_admin_task;
tqg = qgroup_if_config_tqg;
@@ -4360,17 +4425,19 @@ iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid,
default:
panic("unknown net intr type");
}
- GROUPTASK_INIT(gtask, 0, fn, q);
info->ifi_filter = filter;
info->ifi_filter_arg = filter_arg;
info->ifi_task = gtask;
- /* XXX query cpu that rid belongs to */
-
err = _iflib_irq_alloc(ctx, irq, rid, iflib_fast_intr, NULL, info, name);
- if (err != 0)
+ if (err != 0) {
+ device_printf(ctx->ifc_dev, "_iflib_irq_alloc failed %d\n", err);
return (err);
+ }
+ if (type == IFLIB_INTR_ADMIN)
+ return (0);
+
if (tqrid != -1) {
cpuid = find_nth(ctx, &cpus, qid);
taskqgroup_attach_cpu(tqg, gtask, q, cpuid, irq->ii_rid, name);
@@ -4402,13 +4469,6 @@ iflib_softirq_alloc_generic(if_ctx_t ctx, int rid, iflib_intr_type_t type, void
tqg = qgroup_if_io_tqg;
fn = _task_fn_rx;
break;
- case IFLIB_INTR_ADMIN:
- q = ctx;
- gtask = &ctx->ifc_admin_task;
- tqg = qgroup_if_config_tqg;
- rid = -1;
- fn = _task_fn_admin;
- break;
case IFLIB_INTR_IOV:
q = ctx;
gtask = &ctx->ifc_vflr_task;
@@ -4965,7 +5025,6 @@ iflib_add_device_sysctl_post(if_ctx_t ctx)
SYSCTL_ADD_COUNTER_U64(ctx_list, queue_list, OID_AUTO, "r_abdications",
CTLFLAG_RD, &txq->ift_br[0]->abdications,
"# of consumer abdications in the mp_ring for this queue");
-
}
if (scctx->isc_nrxqsets > 100)
@@ -4987,6 +5046,7 @@ iflib_add_device_sysctl_post(if_ctx_t ctx)
CTLFLAG_RD,
&rxq->ifr_cq_cidx, 1, "Consumer Index");
}
+
for (j = 0, fl = rxq->ifr_fl; j < rxq->ifr_nfl; j++, fl++) {
snprintf(namebuf, NAME_BUFLEN, "rxq_fl%d", j);
fl_node = SYSCTL_ADD_NODE(ctx_list, queue_list, OID_AUTO, namebuf,
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 91158b0fccc9..5f14287d10cc 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1566,8 +1566,8 @@ sysctl_dumpentry(struct radix_node *rn, void *vw)
}
static int
-sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info,
- struct walkarg *w, int len)
+sysctl_iflist_ifml(struct ifnet *ifp, const struct if_data *src_ifd,
+ struct rt_addrinfo *info, struct walkarg *w, int len)
{
struct if_msghdrl *ifm;
struct if_data *ifd;
@@ -1598,14 +1598,14 @@ sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info,
ifd = &ifm->ifm_data;
}
- if_data_copy(ifp, ifd);
+ memcpy(ifd, src_ifd, sizeof(*ifd));
return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
}
static int
-sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info,
- struct walkarg *w, int len)
+sysctl_iflist_ifm(struct ifnet *ifp, const struct if_data *src_ifd,
+ struct rt_addrinfo *info, struct walkarg *w, int len)
{
struct if_msghdr *ifm;
struct if_data *ifd;
@@ -1630,7 +1630,7 @@ sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info,
ifd = &ifm->ifm_data;
}
- if_data_copy(ifp, ifd);
+ memcpy(ifd, src_ifd, sizeof(*ifd));
return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
}
@@ -1705,15 +1705,18 @@ sysctl_iflist(int af, struct walkarg *w)
{
struct ifnet *ifp;
struct ifaddr *ifa;
+ struct if_data ifd;
struct rt_addrinfo info;
int len, error = 0;
struct sockaddr_storage ss;
bzero((caddr_t)&info, sizeof(info));
+ bzero(&ifd, sizeof(ifd));
IFNET_RLOCK_NOSLEEP();
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (w->w_arg && w->w_arg != ifp->if_index)
continue;
+ if_data_copy(ifp, &ifd);
IF_ADDR_RLOCK(ifp);
ifa = ifp->if_addr;
info.rti_info[RTAX_IFP] = ifa->ifa_addr;
@@ -1723,9 +1726,11 @@ sysctl_iflist(int af, struct walkarg *w)
info.rti_info[RTAX_IFP] = NULL;
if (w->w_req && w->w_tmem) {
if (w->w_op == NET_RT_IFLISTL)
- error = sysctl_iflist_ifml(ifp, &info, w, len);
+ error = sysctl_iflist_ifml(ifp, &ifd, &info, w,
+ len);
else
- error = sysctl_iflist_ifm(ifp, &info, w, len);
+ error = sysctl_iflist_ifm(ifp, &ifd, &info, w,
+ len);
if (error)
goto done;
}
@@ -1768,13 +1773,15 @@ done:
static int
sysctl_ifmalist(int af, struct walkarg *w)
{
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- struct rt_addrinfo info;
- int len, error = 0;
+ struct rt_addrinfo info;
struct ifaddr *ifa;
+ struct ifmultiaddr *ifma;
+ struct ifnet *ifp;
+ int error, len;
+ error = 0;
bzero((caddr_t)&info, sizeof(info));
+
IFNET_RLOCK_NOSLEEP();
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (w->w_arg && w->w_arg != ifp->if_index)
@@ -1794,7 +1801,7 @@ sysctl_ifmalist(int af, struct walkarg *w)
ifma->ifma_lladdr : NULL;
error = rtsock_msg_buffer(RTM_NEWMADDR, &info, w, &len);
if (error != 0)
- goto done;
+ break;
if (w->w_req && w->w_tmem) {
struct ifma_msghdr *ifmam;
@@ -1803,15 +1810,14 @@ sysctl_ifmalist(int af, struct walkarg *w)
ifmam->ifmam_flags = 0;
ifmam->ifmam_addrs = info.rti_addrs;
error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
- if (error) {
- IF_ADDR_RUNLOCK(ifp);
- goto done;
- }
+ if (error != 0)
+ break;
}
}
IF_ADDR_RUNLOCK(ifp);
+ if (error != 0)
+ break;
}
-done:
IFNET_RUNLOCK_NOSLEEP();
return (error);
}
diff --git a/sys/net80211/_ieee80211.h b/sys/net80211/_ieee80211.h
index aceaba57cb0e..7a33b53a2322 100644
--- a/sys/net80211/_ieee80211.h
+++ b/sys/net80211/_ieee80211.h
@@ -402,4 +402,71 @@ struct ieee80211_mimo_info {
uint8_t pad[2];
uint32_t evm[3]; /* EVM data */
};
+
+/*
+ * ic_caps/iv_caps: device driver capabilities
+ */
+/* 0x2e available */
+#define IEEE80211_C_STA 0x00000001 /* CAPABILITY: STA available */
+#define IEEE80211_C_8023ENCAP 0x00000002 /* CAPABILITY: 802.3 encap */
+#define IEEE80211_C_FF 0x00000040 /* CAPABILITY: ATH FF avail */
+#define IEEE80211_C_TURBOP 0x00000080 /* CAPABILITY: ATH Turbo avail*/
+#define IEEE80211_C_IBSS 0x00000100 /* CAPABILITY: IBSS available */
+#define IEEE80211_C_PMGT 0x00000200 /* CAPABILITY: Power mgmt */
+#define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */
+#define IEEE80211_C_AHDEMO 0x00000800 /* CAPABILITY: Old Adhoc Demo */
+#define IEEE80211_C_SWRETRY 0x00001000 /* CAPABILITY: sw tx retry */
+#define IEEE80211_C_TXPMGT 0x00002000 /* CAPABILITY: tx power mgmt */
+#define IEEE80211_C_SHSLOT 0x00004000 /* CAPABILITY: short slottime */
+#define IEEE80211_C_SHPREAMBLE 0x00008000 /* CAPABILITY: short preamble */
+#define IEEE80211_C_MONITOR 0x00010000 /* CAPABILITY: monitor mode */
+#define IEEE80211_C_DFS 0x00020000 /* CAPABILITY: DFS/radar avail*/
+#define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */
+#define IEEE80211_C_SWSLEEP 0x00080000 /* CAPABILITY: do sleep here */
+#define IEEE80211_C_SWAMSDUTX 0x00100000 /* CAPABILITY: software A-MSDU TX */
+/* 0x7c0000 available */
+#define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */
+#define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */
+#define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/
+#define IEEE80211_C_BURST 0x02000000 /* CAPABILITY: frame bursting */
+#define IEEE80211_C_WME 0x04000000 /* CAPABILITY: WME avail */
+#define IEEE80211_C_WDS 0x08000000 /* CAPABILITY: 4-addr support */
+/* 0x10000000 reserved */
+#define IEEE80211_C_BGSCAN 0x20000000 /* CAPABILITY: bg scanning */
+#define IEEE80211_C_TXFRAG 0x40000000 /* CAPABILITY: tx fragments */
+#define IEEE80211_C_TDMA 0x80000000 /* CAPABILITY: TDMA avail */
+/* XXX protection/barker? */
+
+#define IEEE80211_C_OPMODE \
+ (IEEE80211_C_STA | IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | \
+ IEEE80211_C_AHDEMO | IEEE80211_C_MONITOR | IEEE80211_C_WDS | \
+ IEEE80211_C_TDMA | IEEE80211_C_MBSS)
+
+#define IEEE80211_C_BITS \
+ "\20\1STA\002803ENCAP\7FF\10TURBOP\11IBSS\12PMGT" \
+ "\13HOSTAP\14AHDEMO\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE" \
+ "\21MONITOR\22DFS\23MBSS\30WPA1\31WPA2\32BURST\33WME\34WDS\36BGSCAN" \
+ "\37TXFRAG\40TDMA"
+
+/*
+ * ic_htcaps/iv_htcaps: HT-specific device/driver capabilities
+ *
+ * NB: the low 16-bits are the 802.11 definitions, the upper
+ * 16-bits are used to define s/w/driver capabilities.
+ */
+#define IEEE80211_HTC_AMPDU 0x00010000 /* CAPABILITY: A-MPDU tx */
+#define IEEE80211_HTC_AMSDU 0x00020000 /* CAPABILITY: A-MSDU tx */
+/* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */
+#define IEEE80211_HTC_HT 0x00040000 /* CAPABILITY: HT operation */
+#define IEEE80211_HTC_SMPS 0x00080000 /* CAPABILITY: MIMO power save*/
+#define IEEE80211_HTC_RIFS 0x00100000 /* CAPABILITY: RIFS support */
+#define IEEE80211_HTC_RXUNEQUAL 0x00200000 /* CAPABILITY: RX unequal MCS */
+#define IEEE80211_HTC_RXMCS32 0x00400000 /* CAPABILITY: MCS32 support */
+#define IEEE80211_HTC_TXUNEQUAL 0x00800000 /* CAPABILITY: TX unequal MCS */
+#define IEEE80211_HTC_TXMCS32 0x01000000 /* CAPABILITY: MCS32 support */
+
+#define IEEE80211_C_HTCAP_BITS \
+ "\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \
+ "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS"
+
#endif /* _NET80211__IEEE80211_H_ */
diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c
index 8362f54bf1a7..f32892651e4e 100644
--- a/sys/net80211/ieee80211_adhoc.c
+++ b/sys/net80211/ieee80211_adhoc.c
@@ -120,9 +120,9 @@ adhoc_vattach(struct ieee80211vap *vap)
static void
sta_leave(void *arg, struct ieee80211_node *ni)
{
- struct ieee80211vap *vap = arg;
+ struct ieee80211vap *vap = ni->ni_vap;
- if (ni->ni_vap == vap && ni != vap->iv_bss)
+ if (ni != vap->iv_bss)
ieee80211_node_leave(ni);
}
@@ -164,7 +164,8 @@ adhoc_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
switch (ostate) {
case IEEE80211_S_RUN: /* beacon miss */
/* purge station table; entries are stale */
- ieee80211_iterate_nodes(&ic->ic_sta, sta_leave, vap);
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap,
+ sta_leave, NULL);
/* fall thru... */
case IEEE80211_S_INIT:
if (vap->iv_des_chan != IEEE80211_CHAN_ANYC &&
@@ -315,6 +316,16 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
int hdrspace, need_tap = 1; /* mbuf need to be tapped. */
uint8_t dir, type, subtype, qos;
uint8_t *bssid;
+ int is_hw_decrypted = 0;
+ int has_decrypted = 0;
+
+ /*
+ * Some devices do hardware decryption all the way through
+ * to pretending the frame wasn't encrypted in the first place.
+ * So, tag it appropriately so it isn't discarded inappropriately.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED))
+ is_hw_decrypted = 1;
if (m->m_flags & M_AMPDU_MPDU) {
/*
@@ -478,7 +489,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
* crypto cipher modules used to do delayed update
* of replay sequence numbers.
*/
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {
/*
* Discard encrypted frames when privacy is off.
@@ -489,14 +500,14 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
IEEE80211_NODE_STAT(ni, rx_noprivacy);
goto out;
}
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
IEEE80211_NODE_STAT(ni, rx_wepfail);
goto out;
}
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ has_decrypted = 1;
} else {
/* XXX M_WEP and IEEE80211_F_PRIVACY */
key = NULL;
@@ -527,7 +538,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
/*
* Next strip any MSDU crypto bits.
*/
- if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) {
+ if (!ieee80211_crypto_demic(vap, key, m, 0)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
ni->ni_macaddr, "data", "%s", "demic error");
vap->iv_stats.is_rx_demicfail++;
@@ -581,7 +592,8 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
* any non-PAE frames received without encryption.
*/
if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
- (key == NULL && (m->m_flags & M_WEP) == 0) &&
+ ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) &&
+ (is_hw_decrypted == 0) &&
eh->ether_type != htons(ETHERTYPE_PAE)) {
/*
* Drop unencrypted frames.
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index 28bbddaf87ca..9b0dc1e2dfdc 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -580,8 +580,9 @@ ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m)
* Validate and strip privacy headers (and trailer) for a
* received frame that has the WEP/Privacy bit set.
*/
-struct ieee80211_key *
-ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen)
+int
+ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen,
+ struct ieee80211_key **key)
{
#define IEEE80211_WEP_HDRLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
#define IEEE80211_WEP_MINLEN \
@@ -590,16 +591,38 @@ ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen)
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_key *k;
struct ieee80211_frame *wh;
+ const struct ieee80211_rx_stats *rxs;
const struct ieee80211_cipher *cip;
uint8_t keyid;
+ /*
+ * Check for hardware decryption and IV stripping.
+ * If the IV is stripped then we definitely can't find a key.
+ * Set the key to NULL but return true; upper layers
+ * will need to handle a NULL key for a successful
+ * decrypt.
+ */
+ rxs = ieee80211_get_rx_params_ptr(m);
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) {
+ if (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP) {
+ /*
+ * Hardware decrypted, IV stripped.
+ * We can't find a key with a stripped IV.
+ * Return successful.
+ */
+ *key = NULL;
+ return (1);
+ }
+ }
+
/* NB: this minimum size data frame could be bigger */
if (m->m_pkthdr.len < IEEE80211_WEP_MINLEN) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY,
"%s: WEP data frame too short, len %u\n",
__func__, m->m_pkthdr.len);
vap->iv_stats.is_rx_tooshort++; /* XXX need unique stat? */
- return NULL;
+ *key = NULL;
+ return (0);
}
/*
@@ -625,15 +648,29 @@ ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen)
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
"unable to pullup %s header", cip->ic_name);
vap->iv_stats.is_rx_wepfail++; /* XXX */
- return NULL;
+ *key = NULL;
+ return (0);
+ }
+
+ /*
+ * Attempt decryption.
+ *
+ * If we fail then don't return the key - return NULL
+ * and an error.
+ */
+ if (cip->ic_decap(k, m, hdrlen)) {
+ /* success */
+ *key = k;
+ return (1);
}
- return (cip->ic_decap(k, m, hdrlen) ? k : NULL);
+ /* Failure */
+ *key = NULL;
+ return (0);
#undef IEEE80211_WEP_MINLEN
#undef IEEE80211_WEP_HDRLEN
}
-
/*
* Check and remove any MIC.
*/
diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h
index 3d1f8cc5e002..c5d64bf91b68 100644
--- a/sys/net80211/ieee80211_crypto.h
+++ b/sys/net80211/ieee80211_crypto.h
@@ -114,7 +114,8 @@ struct ieee80211_key {
#define IEEE80211_KEY_DEVICE /* flags owned by device driver */\
(IEEE80211_KEY_DEVKEY|IEEE80211_KEY_CIPHER0|IEEE80211_KEY_CIPHER1| \
- IEEE80211_KEY_SWCRYPT|IEEE80211_KEY_SWMIC)
+ IEEE80211_KEY_SWCRYPT|IEEE80211_KEY_SWMIC|IEEE80211_KEY_NOIV | \
+ IEEE80211_KEY_NOIVMGT|IEEE80211_KEY_NOMIC|IEEE80211_KEY_NOMICMGT)
#define IEEE80211_KEY_BITS \
"\20\1XMIT\2RECV\3GROUP\4SWENCRYPT\5SWDECRYPT\6SWENMIC\7SWDEMIC" \
@@ -207,8 +208,8 @@ struct ieee80211_key *ieee80211_crypto_get_txkey(struct ieee80211_node *,
struct mbuf *);
struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
struct mbuf *);
-struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *,
- struct mbuf *, int);
+int ieee80211_crypto_decap(struct ieee80211_node *,
+ struct mbuf *, int, struct ieee80211_key **);
int ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
struct mbuf *, int);
/*
diff --git a/sys/net80211/ieee80211_crypto_ccmp.c b/sys/net80211/ieee80211_crypto_ccmp.c
index 9fdd5e08ee90..90e1c0733d09 100644
--- a/sys/net80211/ieee80211_crypto_ccmp.c
+++ b/sys/net80211/ieee80211_crypto_ccmp.c
@@ -162,12 +162,27 @@ ccmp_setiv(struct ieee80211_key *k, uint8_t *ivp)
static int
ccmp_encap(struct ieee80211_key *k, struct mbuf *m)
{
+ const struct ieee80211_frame *wh;
struct ccmp_ctx *ctx = k->wk_private;
struct ieee80211com *ic = ctx->cc_ic;
uint8_t *ivp;
int hdrlen;
+ int is_mgmt;
hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
+ wh = mtod(m, const struct ieee80211_frame *);
+ is_mgmt = IEEE80211_IS_MGMT(wh);
+
+ /*
+ * Check to see if we need to insert IV/MIC.
+ *
+ * Some offload devices don't require the IV to be inserted
+ * as part of the hardware encryption.
+ */
+ if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOIVMGT))
+ return 1;
+ if ((! is_mgmt) && (k->wk_flags & IEEE80211_KEY_NOIV))
+ return 1;
/*
* Copy down 802.11 header and add the IV, KeyID, and ExtIV.
@@ -217,12 +232,18 @@ READ_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5)
static int
ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
{
+ const struct ieee80211_rx_stats *rxs;
struct ccmp_ctx *ctx = k->wk_private;
struct ieee80211vap *vap = ctx->cc_vap;
struct ieee80211_frame *wh;
uint8_t *ivp, tid;
uint64_t pn;
+ rxs = ieee80211_get_rx_params_ptr(m);
+
+ if ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))
+ goto finish;
+
/*
* Header should have extended IV and sequence number;
* verify the former and validate the latter.
@@ -261,17 +282,28 @@ ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
!ccmp_decrypt(k, pn, m, hdrlen))
return 0;
+finish:
/*
* Copy up 802.11 header and strip crypto bits.
*/
- ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + ccmp.ic_header, hdrlen);
- m_adj(m, ccmp.ic_header);
- m_adj(m, -ccmp.ic_trailer);
+ if (! ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) {
+ ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + ccmp.ic_header,
+ hdrlen);
+ m_adj(m, ccmp.ic_header);
+ }
+
+ /*
+ * XXX TODO: see if MMIC_STRIP also covers CCMP MIC trailer.
+ */
+ if (! ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP)))
+ m_adj(m, -ccmp.ic_trailer);
/*
* Ok to update rsc now.
*/
- k->wk_keyrsc[tid] = pn;
+ if (! ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) {
+ k->wk_keyrsc[tid] = pn;
+ }
return 1;
}
diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c
index 8b33a7919762..20258fa05e37 100644
--- a/sys/net80211/ieee80211_crypto_tkip.c
+++ b/sys/net80211/ieee80211_crypto_tkip.c
@@ -177,8 +177,13 @@ tkip_encap(struct ieee80211_key *k, struct mbuf *m)
struct tkip_ctx *ctx = k->wk_private;
struct ieee80211vap *vap = ctx->tc_vap;
struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_frame *wh;
uint8_t *ivp;
int hdrlen;
+ int is_mgmt;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ is_mgmt = IEEE80211_IS_MGMT(wh);
/*
* Handle TKIP counter measures requirement.
@@ -193,6 +198,16 @@ tkip_encap(struct ieee80211_key *k, struct mbuf *m)
vap->iv_stats.is_crypto_tkipcm++;
return 0;
}
+
+ /*
+ * Check to see whether IV needs to be included.
+ */
+ if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOIVMGT))
+ return 1;
+ if ((! is_mgmt) && (k->wk_flags & IEEE80211_KEY_NOIV))
+ return 1;
+
+
hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
/*
@@ -224,6 +239,19 @@ static int
tkip_enmic(struct ieee80211_key *k, struct mbuf *m, int force)
{
struct tkip_ctx *ctx = k->wk_private;
+ struct ieee80211_frame *wh;
+ int is_mgmt;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ is_mgmt = IEEE80211_IS_MGMT(wh);
+
+ /*
+ * Check to see whether MIC needs to be included.
+ */
+ if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOMICMGT))
+ return 1;
+ if ((! is_mgmt) && (k->wk_flags & IEEE80211_KEY_NOMIC))
+ return 1;
if (force || (k->wk_flags & IEEE80211_KEY_SWENMIC)) {
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
@@ -259,11 +287,20 @@ READ_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5)
static int
tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
{
+ const struct ieee80211_rx_stats *rxs;
struct tkip_ctx *ctx = k->wk_private;
struct ieee80211vap *vap = ctx->tc_vap;
struct ieee80211_frame *wh;
uint8_t *ivp, tid;
+ rxs = ieee80211_get_rx_params_ptr(m);
+
+ /*
+ * If IV has been stripped, we skip most of the below.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))
+ goto finish;
+
/*
* Header should have extended IV and sequence number;
* verify the former and validate the latter.
@@ -318,11 +355,22 @@ tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
!tkip_decrypt(ctx, k, m, hdrlen))
return 0;
+finish:
+
+ /*
+ * Copy up 802.11 header and strip crypto bits - but only if we
+ * are required to.
+ */
+ if (! ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) {
+ memmove(mtod(m, uint8_t *) + tkip.ic_header, mtod(m, void *),
+ hdrlen);
+ m_adj(m, tkip.ic_header);
+ }
+
/*
- * Copy up 802.11 header and strip crypto bits.
+ * XXX TODO: do we need an option to potentially not strip the
+ * WEP trailer? Does "MMIC_STRIP" also mean this? Or?
*/
- memmove(mtod(m, uint8_t *) + tkip.ic_header, mtod(m, void *), hdrlen);
- m_adj(m, tkip.ic_header);
m_adj(m, -tkip.ic_trailer);
return 1;
@@ -334,11 +382,33 @@ tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
static int
tkip_demic(struct ieee80211_key *k, struct mbuf *m, int force)
{
+ const struct ieee80211_rx_stats *rxs;
struct tkip_ctx *ctx = k->wk_private;
struct ieee80211_frame *wh;
uint8_t tid;
wh = mtod(m, struct ieee80211_frame *);
+ rxs = ieee80211_get_rx_params_ptr(m);
+
+ /*
+ * If we are told about a MIC failure from the driver,
+ * directly notify as a michael failure to the upper
+ * layers.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_FAIL_MIC)) {
+ struct ieee80211vap *vap = ctx->tc_vap;
+ ieee80211_notify_michael_failure(vap, wh,
+ k->wk_rxkeyix != IEEE80211_KEYIX_NONE ?
+ k->wk_rxkeyix : k->wk_keyix);
+ return 0;
+ }
+
+ /*
+ * If IV has been stripped, we skip most of the below.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP))
+ goto finish;
+
if ((k->wk_flags & IEEE80211_KEY_SWDEMIC) || force) {
struct ieee80211vap *vap = ctx->tc_vap;
int hdrlen = ieee80211_hdrspace(vap->iv_ic, wh);
@@ -371,6 +441,7 @@ tkip_demic(struct ieee80211_key *k, struct mbuf *m, int force)
tid = ieee80211_gettid(wh);
k->wk_keyrsc[tid] = ctx->rx_rsc;
+finish:
return 1;
}
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
index 5a9a301e74b9..9868f133bca7 100644
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -107,9 +107,8 @@ hostap_vattach(struct ieee80211vap *vap)
static void
sta_disassoc(void *arg, struct ieee80211_node *ni)
{
- struct ieee80211vap *vap = arg;
- if (ni->ni_vap == vap && ni->ni_associd != 0) {
+ if (ni->ni_associd != 0) {
IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DISASSOC,
IEEE80211_REASON_ASSOC_LEAVE);
ieee80211_node_leave(ni);
@@ -119,9 +118,9 @@ sta_disassoc(void *arg, struct ieee80211_node *ni)
static void
sta_csa(void *arg, struct ieee80211_node *ni)
{
- struct ieee80211vap *vap = arg;
+ struct ieee80211vap *vap = ni->ni_vap;
- if (ni->ni_vap == vap && ni->ni_associd != 0)
+ if (ni->ni_associd != 0)
if (ni->ni_inact > vap->iv_inact_init) {
ni->ni_inact = vap->iv_inact_init;
IEEE80211_NOTE(vap, IEEE80211_MSG_INACT, ni,
@@ -132,9 +131,8 @@ sta_csa(void *arg, struct ieee80211_node *ni)
static void
sta_drop(void *arg, struct ieee80211_node *ni)
{
- struct ieee80211vap *vap = arg;
- if (ni->ni_vap == vap && ni->ni_associd != 0)
+ if (ni->ni_associd != 0)
ieee80211_node_leave(ni);
}
@@ -179,7 +177,8 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_dfs_cac_stop(vap);
break;
case IEEE80211_S_RUN:
- ieee80211_iterate_nodes(&ic->ic_sta, sta_disassoc, vap);
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap,
+ sta_disassoc, NULL);
break;
default:
break;
@@ -195,7 +194,8 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
switch (ostate) {
case IEEE80211_S_CSA:
case IEEE80211_S_RUN:
- ieee80211_iterate_nodes(&ic->ic_sta, sta_disassoc, vap);
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap,
+ sta_disassoc, NULL);
/*
* Clear overlapping BSS state; the beacon frame
* will be reconstructed on transition to the RUN
@@ -289,7 +289,8 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* Shorten inactivity timer of associated stations
* to weed out sta's that don't follow a CSA.
*/
- ieee80211_iterate_nodes(&ic->ic_sta, sta_csa, vap);
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap,
+ sta_csa, NULL);
/*
* Update bss node channel to reflect where
* we landed after CSA.
@@ -340,7 +341,8 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* such as capabilities and the negotiated rate
* set may/will be wrong).
*/
- ieee80211_iterate_nodes(&ic->ic_sta, sta_drop, vap);
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap,
+ sta_drop, NULL);
}
break;
default:
@@ -477,6 +479,16 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
int hdrspace, need_tap = 1; /* mbuf need to be tapped. */
uint8_t dir, type, subtype, qos;
uint8_t *bssid;
+ int is_hw_decrypted = 0;
+ int has_decrypted = 0;
+
+ /*
+ * Some devices do hardware decryption all the way through
+ * to pretending the frame wasn't encrypted in the first place.
+ * So, tag it appropriately so it isn't discarded inappropriately.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED))
+ is_hw_decrypted = 1;
if (m->m_flags & M_AMPDU_MPDU) {
/*
@@ -666,7 +678,7 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
* crypto cipher modules used to do delayed update
* of replay sequence numbers.
*/
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {
/*
* Discard encrypted frames when privacy is off.
@@ -677,14 +689,14 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
IEEE80211_NODE_STAT(ni, rx_noprivacy);
goto out;
}
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
IEEE80211_NODE_STAT(ni, rx_wepfail);
goto out;
}
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ has_decrypted = 1;
} else {
/* XXX M_WEP and IEEE80211_F_PRIVACY */
key = NULL;
@@ -767,7 +779,8 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
* any non-PAE frames received without encryption.
*/
if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
- (key == NULL && (m->m_flags & M_WEP) == 0) &&
+ ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) &&
+ (is_hw_decrypted == 0) &&
eh->ether_type != htons(ETHERTYPE_PAE)) {
/*
* Drop unencrypted frames.
@@ -849,13 +862,13 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
goto out;
}
hdrspace = ieee80211_hdrspace(ic, wh);
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
goto out;
}
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ has_decrypted = 1;
}
/*
* Pass the packet to radiotap before calling iv_recv_mgmt().
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 5d323c05a53d..3a797d8175af 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -347,7 +347,6 @@ ieee80211_ioctl_getscanresults(struct ieee80211vap *vap,
}
struct stainforeq {
- struct ieee80211vap *vap;
struct ieee80211req_sta_info *si;
size_t space;
};
@@ -366,8 +365,6 @@ get_sta_space(void *arg, struct ieee80211_node *ni)
struct stainforeq *req = arg;
size_t ielen;
- if (req->vap != ni->ni_vap)
- return;
if (ni->ni_vap->iv_opmode == IEEE80211_M_HOSTAP &&
ni->ni_associd == 0) /* only associated stations */
return;
@@ -383,8 +380,6 @@ get_sta_info(void *arg, struct ieee80211_node *ni)
size_t ielen, len;
uint8_t *cp;
- if (req->vap != ni->ni_vap)
- return;
if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
ni->ni_associd == 0) /* only associated stations */
return;
@@ -472,10 +467,10 @@ getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
error = 0;
req.space = 0;
- req.vap = vap;
- if (ni == NULL)
- ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req);
- else
+ if (ni == NULL) {
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, get_sta_space,
+ &req);
+ } else
get_sta_space(&req, ni);
if (req.space > ireq->i_len)
req.space = ireq->i_len;
@@ -489,9 +484,10 @@ getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
goto bad;
}
req.si = p;
- if (ni == NULL)
- ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req);
- else
+ if (ni == NULL) {
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap,
+ get_sta_info, &req);
+ } else
get_sta_info(&req, ni);
ireq->i_len = space - req.space;
error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 80c61f169ec4..05746ad9561e 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -2717,7 +2717,6 @@ done:
}
struct rssiinfo {
- struct ieee80211vap *vap;
int rssi_samples;
uint32_t rssi_total;
};
@@ -2729,8 +2728,6 @@ get_hostap_rssi(void *arg, struct ieee80211_node *ni)
struct ieee80211vap *vap = ni->ni_vap;
int8_t rssi;
- if (info->vap != vap)
- return;
/* only associated stations */
if (ni->ni_associd == 0)
return;
@@ -2748,8 +2745,6 @@ get_adhoc_rssi(void *arg, struct ieee80211_node *ni)
struct ieee80211vap *vap = ni->ni_vap;
int8_t rssi;
- if (info->vap != vap)
- return;
/* only neighbors */
/* XXX check bssid */
if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
@@ -2769,8 +2764,6 @@ get_mesh_rssi(void *arg, struct ieee80211_node *ni)
struct ieee80211vap *vap = ni->ni_vap;
int8_t rssi;
- if (info->vap != vap)
- return;
/* only neighbors that peered successfully */
if (ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
return;
@@ -2791,18 +2784,20 @@ ieee80211_getrssi(struct ieee80211vap *vap)
info.rssi_total = 0;
info.rssi_samples = 0;
- info.vap = vap;
switch (vap->iv_opmode) {
case IEEE80211_M_IBSS: /* average of all ibss neighbors */
case IEEE80211_M_AHDEMO: /* average of all neighbors */
- ieee80211_iterate_nodes(&ic->ic_sta, get_adhoc_rssi, &info);
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, get_adhoc_rssi,
+ &info);
break;
case IEEE80211_M_HOSTAP: /* average of all associated stations */
- ieee80211_iterate_nodes(&ic->ic_sta, get_hostap_rssi, &info);
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, get_hostap_rssi,
+ &info);
break;
#ifdef IEEE80211_SUPPORT_MESH
case IEEE80211_M_MBSS: /* average of all mesh neighbors */
- ieee80211_iterate_nodes(&ic->ic_sta, get_mesh_rssi, &info);
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, get_mesh_rssi,
+ &info);
break;
#endif
case IEEE80211_M_MONITOR: /* XXX */
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index 5a6cce625b92..c71f8541085b 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -2074,6 +2074,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211_node *bss;
const struct ieee80211_txparam *tp;
struct ieee80211_bpf_params params;
const struct ieee80211_rateset *rs;
@@ -2081,10 +2082,13 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
uint8_t *frm;
int ret;
+ bss = ieee80211_ref_node(vap->iv_bss);
+
if (vap->iv_state == IEEE80211_S_CAC) {
IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni,
"block %s frame in CAC state", "probe request");
vap->iv_stats.is_tx_badstate++;
+ ieee80211_free_node(bss);
return EIO; /* XXX */
}
@@ -2106,6 +2110,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
* [tlv] supported rates
* [tlv] RSN (optional)
* [tlv] extended supported rates
+ * [tlv] HT cap (optional)
* [tlv] WPA (optional)
* [tlv] user-specified ie's
*/
@@ -2113,6 +2118,8 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
ic->ic_headroom + sizeof(struct ieee80211_frame),
2 + IEEE80211_NWID_LEN
+ 2 + IEEE80211_RATE_SIZE
+ + sizeof(struct ieee80211_ie_htcap)
+ + sizeof(struct ieee80211_ie_htinfo)
+ sizeof(struct ieee80211_ie_wpa)
+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
+ sizeof(struct ieee80211_ie_wpa)
@@ -2122,6 +2129,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
if (m == NULL) {
vap->iv_stats.is_tx_nobuf++;
ieee80211_free_node(ni);
+ ieee80211_free_node(bss);
return ENOMEM;
}
@@ -2130,6 +2138,27 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
frm = ieee80211_add_rates(frm, rs);
frm = ieee80211_add_rsn(frm, vap);
frm = ieee80211_add_xrates(frm, rs);
+
+ /*
+ * Note: we can't use bss; we don't have one yet.
+ *
+ * So, we should announce our capabilities
+ * in this channel mode (2g/5g), not the
+ * channel details itself.
+ */
+ if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
+ (vap->iv_flags_ht & IEEE80211_FHT_HT)) {
+ struct ieee80211_channel *c;
+
+ /*
+ * Get the HT channel that we should try upgrading to.
+ * If we can do 40MHz then this'll upgrade it appropriately.
+ */
+ c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan,
+ vap->iv_flags_ht);
+ frm = ieee80211_add_htcap_ch(frm, vap, c);
+ }
+
frm = ieee80211_add_wpa(frm, vap);
if (vap->iv_appie_probereq != NULL)
frm = add_appie(frm, vap->iv_appie_probereq);
@@ -2141,6 +2170,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
if (m == NULL) {
/* NB: cannot happen */
ieee80211_free_node(ni);
+ ieee80211_free_node(bss);
return ENOMEM;
}
@@ -2157,8 +2187,11 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
IEEE80211_NODE_STAT(ni, tx_mgmt);
IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS,
- "send probe req on channel %u bssid %s ssid \"%.*s\"\n",
- ieee80211_chan2ieee(ic, ic->ic_curchan), ether_sprintf(bssid),
+ "send probe req on channel %u bssid %s sa %6D da %6D ssid \"%.*s\"\n",
+ ieee80211_chan2ieee(ic, ic->ic_curchan),
+ ether_sprintf(bssid),
+ sa, ":",
+ da, ":",
ssidlen, ssid);
memset(&params, 0, sizeof(params));
@@ -2173,6 +2206,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
params.ibp_power = ni->ni_txpower;
ret = ieee80211_raw_output(vap, ni, m, &params);
IEEE80211_TX_UNLOCK(ic);
+ ieee80211_free_node(bss);
return (ret);
}
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index 47b0573639b8..82d65c6ecf73 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -1336,7 +1336,8 @@ sta_roam_check(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
* XXX force immediate switch on scan complete
*/
if (!IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) &&
- ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle))
+ ((vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) ||
+ ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle)))
ieee80211_bg_scan(vap, 0);
return;
}
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index 9100fb0817e3..dd9ef6e4d21a 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -546,6 +546,16 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
int hdrspace, need_tap = 1; /* mbuf need to be tapped. */
uint8_t dir, type, subtype, qos;
uint8_t *bssid;
+ int is_hw_decrypted = 0;
+ int has_decrypted = 0;
+
+ /*
+ * Some devices do hardware decryption all the way through
+ * to pretending the frame wasn't encrypted in the first place.
+ * So, tag it appropriately so it isn't discarded inappropriately.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED))
+ is_hw_decrypted = 1;
if (m->m_flags & M_AMPDU_MPDU) {
/*
@@ -724,6 +734,21 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
}
/*
+ * Handle privacy requirements for hardware decryption
+ * devices.
+ *
+ * For those devices, a handful of things happen.
+ *
+ * + If IV has been stripped, then we can't run
+ * ieee80211_crypto_decap() - none of the key
+ * + If MIC has been stripped, we can't validate
+ * MIC here.
+ * + If MIC fails, then we need to communicate a
+ * MIC failure up to the stack - but we don't know
+ * which key was used.
+ */
+
+ /*
* Handle privacy requirements. Note that we
* must not be preempted from here until after
* we (potentially) call ieee80211_crypto_demic;
@@ -731,7 +756,7 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
* crypto cipher modules used to do delayed update
* of replay sequence numbers.
*/
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {
/*
* Discard encrypted frames when privacy is off.
@@ -742,14 +767,14 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
IEEE80211_NODE_STAT(ni, rx_noprivacy);
goto out;
}
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
IEEE80211_NODE_STAT(ni, rx_wepfail);
goto out;
}
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ has_decrypted = 1;
} else {
/* XXX M_WEP and IEEE80211_F_PRIVACY */
key = NULL;
@@ -779,8 +804,13 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
/*
* Next strip any MSDU crypto bits.
+ *
+ * Note: we can't do MIC stripping/verification if the
+ * upper layer has stripped it. We have to check MIC
+ * ourselves. So, key may be NULL, but we have to check
+ * the RX status.
*/
- if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) {
+ if (!ieee80211_crypto_demic(vap, key, m, 0)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
ni->ni_macaddr, "data", "%s", "demic error");
vap->iv_stats.is_rx_demicfail++;
@@ -834,7 +864,8 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
* any non-PAE frames received without encryption.
*/
if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
- (key == NULL && (m->m_flags & M_WEP) == 0) &&
+ ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) &&
+ (is_hw_decrypted == 0) &&
eh->ether_type != htons(ETHERTYPE_PAE)) {
/*
* Drop unencrypted frames.
@@ -883,6 +914,16 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
ether_sprintf(wh->i_addr2), rssi);
}
#endif
+
+ /*
+ * Note: See above for hardware offload privacy requirements.
+ * It also applies here.
+ */
+
+ /*
+ * Again, having encrypted flag set check would be good, but
+ * then we have to also handle crypto_decap() like above.
+ */
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
if (subtype != IEEE80211_FC0_SUBTYPE_AUTH) {
/*
@@ -905,11 +946,16 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
goto out;
}
hdrspace = ieee80211_hdrspace(ic, wh);
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+
+ /*
+ * Again, if IV/MIC was stripped, then this whole
+ * setup will fail. That's going to need some poking.
+ */
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
goto out;
}
+ has_decrypted = 1;
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
}
@@ -1230,6 +1276,7 @@ done:
* o bg scan is active
* o no channel switch is pending
* o there has not been any traffic recently
+ * o no full-offload scan support (no need for explicitly continuing scan then)
*
* Note we do not check if there is an administrative enable;
* this is only done to start the scan. We assume that any
@@ -1243,6 +1290,7 @@ contbgscan(struct ieee80211vap *vap)
return ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) &&
(ic->ic_flags & IEEE80211_F_CSAPENDING) == 0 &&
+ !(vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) &&
vap->iv_state == IEEE80211_S_RUN && /* XXX? */
ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
}
@@ -1253,7 +1301,7 @@ contbgscan(struct ieee80211vap *vap)
* o no channel switch is pending
* o we are not boosted on a dynamic turbo channel
* o there has not been a scan recently
- * o there has not been any traffic recently
+ * o there has not been any traffic recently (don't check if full-offload scan)
*/
static __inline int
startbgscan(struct ieee80211vap *vap)
@@ -1266,7 +1314,8 @@ startbgscan(struct ieee80211vap *vap)
!IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) &&
#endif
ieee80211_time_after(ticks, ic->ic_lastscan + vap->iv_bgscanintvl) &&
- ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
+ ((vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) ||
+ ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle)));
}
static void
diff --git a/sys/net80211/ieee80211_tdma.c b/sys/net80211/ieee80211_tdma.c
index e85cb9827dee..aac8c7fd55c1 100644
--- a/sys/net80211/ieee80211_tdma.c
+++ b/sys/net80211/ieee80211_tdma.c
@@ -209,9 +209,9 @@ tdma_vdetach(struct ieee80211vap *vap)
static void
sta_leave(void *arg, struct ieee80211_node *ni)
{
- struct ieee80211vap *vap = arg;
+ struct ieee80211vap *vap = ni->ni_vap;
- if (ni->ni_vap == vap && ni != vap->iv_bss)
+ if (ni != vap->iv_bss)
ieee80211_node_leave(ni);
}
@@ -246,7 +246,8 @@ tdma_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_cancel_scan(vap); /* background scan */
if (ostate == IEEE80211_S_RUN) {
/* purge station table; entries are stale */
- ieee80211_iterate_nodes(&ic->ic_sta, sta_leave, vap);
+ ieee80211_iterate_nodes_vap(&ic->ic_sta, vap,
+ sta_leave, NULL);
}
if (vap->iv_flags_ext & IEEE80211_FEXT_SCANREQ) {
ieee80211_check_scan(vap,
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index 479a8d62a825..37f4f6dde7f8 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -633,70 +633,6 @@ MALLOC_DECLARE(M_80211_VAP);
#define IEEE80211_FVEN_BITS "\20"
-/* ic_caps/iv_caps: device driver capabilities */
-/* 0x2e available */
-#define IEEE80211_C_STA 0x00000001 /* CAPABILITY: STA available */
-#define IEEE80211_C_8023ENCAP 0x00000002 /* CAPABILITY: 802.3 encap */
-#define IEEE80211_C_FF 0x00000040 /* CAPABILITY: ATH FF avail */
-#define IEEE80211_C_TURBOP 0x00000080 /* CAPABILITY: ATH Turbo avail*/
-#define IEEE80211_C_IBSS 0x00000100 /* CAPABILITY: IBSS available */
-#define IEEE80211_C_PMGT 0x00000200 /* CAPABILITY: Power mgmt */
-#define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */
-#define IEEE80211_C_AHDEMO 0x00000800 /* CAPABILITY: Old Adhoc Demo */
-#define IEEE80211_C_SWRETRY 0x00001000 /* CAPABILITY: sw tx retry */
-#define IEEE80211_C_TXPMGT 0x00002000 /* CAPABILITY: tx power mgmt */
-#define IEEE80211_C_SHSLOT 0x00004000 /* CAPABILITY: short slottime */
-#define IEEE80211_C_SHPREAMBLE 0x00008000 /* CAPABILITY: short preamble */
-#define IEEE80211_C_MONITOR 0x00010000 /* CAPABILITY: monitor mode */
-#define IEEE80211_C_DFS 0x00020000 /* CAPABILITY: DFS/radar avail*/
-#define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */
-#define IEEE80211_C_SWSLEEP 0x00080000 /* CAPABILITY: do sleep here */
-#define IEEE80211_C_SWAMSDUTX 0x00100000 /* CAPABILITY: software A-MSDU TX */
-/* 0x7c0000 available */
-#define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */
-#define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */
-#define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/
-#define IEEE80211_C_BURST 0x02000000 /* CAPABILITY: frame bursting */
-#define IEEE80211_C_WME 0x04000000 /* CAPABILITY: WME avail */
-#define IEEE80211_C_WDS 0x08000000 /* CAPABILITY: 4-addr support */
-/* 0x10000000 reserved */
-#define IEEE80211_C_BGSCAN 0x20000000 /* CAPABILITY: bg scanning */
-#define IEEE80211_C_TXFRAG 0x40000000 /* CAPABILITY: tx fragments */
-#define IEEE80211_C_TDMA 0x80000000 /* CAPABILITY: TDMA avail */
-/* XXX protection/barker? */
-
-#define IEEE80211_C_OPMODE \
- (IEEE80211_C_STA | IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | \
- IEEE80211_C_AHDEMO | IEEE80211_C_MONITOR | IEEE80211_C_WDS | \
- IEEE80211_C_TDMA | IEEE80211_C_MBSS)
-
-#define IEEE80211_C_BITS \
- "\20\1STA\002803ENCAP\7FF\10TURBOP\11IBSS\12PMGT" \
- "\13HOSTAP\14AHDEMO\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE" \
- "\21MONITOR\22DFS\23MBSS\30WPA1\31WPA2\32BURST\33WME\34WDS\36BGSCAN" \
- "\37TXFRAG\40TDMA"
-
-/*
- * ic_htcaps/iv_htcaps: HT-specific device/driver capabilities
- *
- * NB: the low 16-bits are the 802.11 definitions, the upper
- * 16-bits are used to define s/w/driver capabilities.
- */
-#define IEEE80211_HTC_AMPDU 0x00010000 /* CAPABILITY: A-MPDU tx */
-#define IEEE80211_HTC_AMSDU 0x00020000 /* CAPABILITY: A-MSDU tx */
-/* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */
-#define IEEE80211_HTC_HT 0x00040000 /* CAPABILITY: HT operation */
-#define IEEE80211_HTC_SMPS 0x00080000 /* CAPABILITY: MIMO power save*/
-#define IEEE80211_HTC_RIFS 0x00100000 /* CAPABILITY: RIFS support */
-#define IEEE80211_HTC_RXUNEQUAL 0x00200000 /* CAPABILITY: RX unequal MCS */
-#define IEEE80211_HTC_RXMCS32 0x00400000 /* CAPABILITY: MCS32 support */
-#define IEEE80211_HTC_TXUNEQUAL 0x00800000 /* CAPABILITY: TX unequal MCS */
-#define IEEE80211_HTC_TXMCS32 0x01000000 /* CAPABILITY: MCS32 suport */
-
-#define IEEE80211_C_HTCAP_BITS \
- "\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \
- "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS"
-
int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3);
void ieee80211_ifattach(struct ieee80211com *);
void ieee80211_ifdetach(struct ieee80211com *);
diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c
index 05268e81d71a..038f41292ed2 100644
--- a/sys/net80211/ieee80211_wds.c
+++ b/sys/net80211/ieee80211_wds.c
@@ -417,6 +417,16 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m,
struct ether_header *eh;
int hdrspace, need_tap = 1; /* mbuf need to be tapped. */
uint8_t dir, type, subtype, qos;
+ int is_hw_decrypted = 0;
+ int has_decrypted = 0;
+
+ /*
+ * Some devices do hardware decryption all the way through
+ * to pretending the frame wasn't encrypted in the first place.
+ * So, tag it appropriately so it isn't discarded inappropriately.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED))
+ is_hw_decrypted = 1;
if (m->m_flags & M_AMPDU_MPDU) {
/*
@@ -544,7 +554,7 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m,
* crypto cipher modules used to do delayed update
* of replay sequence numbers.
*/
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {
/*
* Discard encrypted frames when privacy is off.
@@ -555,14 +565,14 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m,
IEEE80211_NODE_STAT(ni, rx_noprivacy);
goto out;
}
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
IEEE80211_NODE_STAT(ni, rx_wepfail);
goto out;
}
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ has_decrypted = 1;
} else {
/* XXX M_WEP and IEEE80211_F_PRIVACY */
key = NULL;
@@ -593,7 +603,7 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m,
/*
* Next strip any MSDU crypto bits.
*/
- if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) {
+ if (!ieee80211_crypto_demic(vap, key, m, 0)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
ni->ni_macaddr, "data", "%s", "demic error");
vap->iv_stats.is_rx_demicfail++;
@@ -647,7 +657,8 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m,
* any non-PAE frames received without encryption.
*/
if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
- (key == NULL && (m->m_flags & M_WEP) == 0) &&
+ ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) &&
+ (is_hw_decrypted == 0) &&
eh->ether_type != htons(ETHERTYPE_PAE)) {
/*
* Drop unencrypted frames.
diff --git a/sys/netgraph/ng_l2tp.c b/sys/netgraph/ng_l2tp.c
index 85cd6c3e340c..55fa2cd31060 100644
--- a/sys/netgraph/ng_l2tp.c
+++ b/sys/netgraph/ng_l2tp.c
@@ -1544,6 +1544,16 @@ ng_l2tp_xmit_ctrl(priv_p priv, struct mbuf *m, u_int16_t ns)
priv->stats.memoryFailures++;
return (ENOBUFS);
}
+
+ /*
+ * The below requires 12 contiguous bytes for the L2TP header
+ * to be written into.
+ */
+ m = m_pullup(m, 12);
+ if (m == NULL) {
+ priv->stats.memoryFailures++;
+ return (ENOBUFS);
+ }
}
/* Fill in L2TP header */
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 63038584274b..dbd27ef1b252 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -2202,9 +2202,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
case TCPS_FIN_WAIT_1:
case TCPS_FIN_WAIT_2:
case TCPS_CLOSE_WAIT:
+ case TCPS_CLOSING:
+ case TCPS_LAST_ACK:
so->so_error = ECONNRESET;
close:
- tcp_state_change(tp, TCPS_CLOSED);
/* FALLTHROUGH */
default:
tp = tcp_close(tp);
diff --git a/sys/netinet/tcp_stacks/fastpath.c b/sys/netinet/tcp_stacks/fastpath.c
index 2d7db04fbc1e..edf46c4f9605 100644
--- a/sys/netinet/tcp_stacks/fastpath.c
+++ b/sys/netinet/tcp_stacks/fastpath.c
@@ -746,9 +746,10 @@ tcp_do_slowpath(struct mbuf *m, struct tcphdr *th, struct socket *so,
case TCPS_FIN_WAIT_1:
case TCPS_FIN_WAIT_2:
case TCPS_CLOSE_WAIT:
+ case TCPS_CLOSING:
+ case TCPS_LAST_ACK:
so->so_error = ECONNRESET;
close:
- tcp_state_change(tp, TCPS_CLOSED);
/* FALLTHROUGH */
default:
tp = tcp_close(tp);
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index f0e76bf18470..c5d059a5fe6c 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1502,6 +1502,7 @@ tcp_discardcb(struct tcpcb *tp)
inp->inp_ppcb = NULL;
if (tp->t_timers->tt_draincnt == 0) {
/* We own the last reference on tcpcb, let's free it. */
+ TCPSTATES_DEC(tp->t_state);
if (tp->t_fb->tfb_tcp_fb_fini)
(*tp->t_fb->tfb_tcp_fb_fini)(tp, 1);
refcount_release(&tp->t_fb->tfb_refcnt);
@@ -1531,6 +1532,7 @@ tcp_timer_discard(void *ptp)
tp->t_timers->tt_draincnt--;
if (tp->t_timers->tt_draincnt == 0) {
/* We own the last reference on this tcpcb, let's free it. */
+ TCPSTATES_DEC(tp->t_state);
if (tp->t_fb->tfb_tcp_fb_fini)
(*tp->t_fb->tfb_tcp_fb_fini)(tp, 1);
refcount_release(&tp->t_fb->tfb_refcnt);
@@ -1577,7 +1579,8 @@ tcp_close(struct tcpcb *tp)
#endif
in_pcbdrop(inp);
TCPSTAT_INC(tcps_closed);
- TCPSTATES_DEC(tp->t_state);
+ if (tp->t_state != TCPS_CLOSED)
+ tcp_state_change(tp, TCPS_CLOSED);
KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL"));
so = inp->inp_socket;
soisdisconnected(so);
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 27b965ea2655..0253ccbc8db9 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -340,6 +340,7 @@ tcp_twstart(struct tcpcb *tp)
tcp_twrespond(tw, TH_ACK);
inp->inp_ppcb = tw;
inp->inp_flags |= INP_TIMEWAIT;
+ TCPSTATES_INC(TCPS_TIME_WAIT);
tcp_tw_2msl_reset(tw, 0);
/*
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index a04aba898419..5faf8a8937c0 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -872,10 +872,11 @@ pte_remove(mmu_t mmu, pmap_t pmap, vm_offset_t va, uint8_t flags)
if (PTE_ISWIRED(pte))
pmap->pm_stats.wired_count--;
+ /* Get vm_page_t for mapped pte. */
+ m = PHYS_TO_VM_PAGE(PTE_PA(pte));
+
/* Handle managed entry. */
if (PTE_ISMANAGED(pte)) {
- /* Get vm_page_t for mapped pte. */
- m = PHYS_TO_VM_PAGE(PTE_PA(pte));
if (PTE_ISMODIFIED(pte))
vm_page_dirty(m);
@@ -884,6 +885,15 @@ pte_remove(mmu_t mmu, pmap_t pmap, vm_offset_t va, uint8_t flags)
vm_page_aflag_set(m, PGA_REFERENCED);
pv_remove(pmap, va, m);
+ } else if (m->md.pv_tracked) {
+ /*
+ * Always pv_insert()/pv_remove() on MPC85XX, in case DPAA is
+ * used. This is needed by the NCSW support code for fast
+ * VA<->PA translation.
+ */
+ pv_remove(pmap, va, m);
+ if (TAILQ_EMPTY(&m->md.pv_list))
+ m->md.pv_tracked = false;
}
mtx_lock_spin(&tlbivax_mutex);
@@ -3466,6 +3476,33 @@ pmap_early_io_map(vm_paddr_t pa, vm_size_t size)
return (va);
}
+void
+pmap_track_page(pmap_t pmap, vm_offset_t va)
+{
+ vm_paddr_t pa;
+ vm_page_t page;
+ struct pv_entry *pve;
+
+ va &= ~PAGE_MASK;
+ pa = pmap_kextract(va);
+
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ page = PHYS_TO_VM_PAGE(pa);
+
+ TAILQ_FOREACH(pve, &page->md.pv_list, pv_link) {
+ if ((pmap == pve->pv_pmap) && (va == pve->pv_va)) {
+ goto out;
+ }
+ }
+ page->md.pv_tracked = true;
+ pv_insert(pmap, va, page);
+out:
+ PMAP_UNLOCK(pmap);
+ rw_wunlock(&pvh_global_lock);
+}
+
+
/*
* Setup MAS4 defaults.
* These values are loaded to MAS0-2 on a TLB miss.
diff --git a/sys/powerpc/conf/MPC85XX b/sys/powerpc/conf/MPC85XX
index b26340fe5397..f3ae67d6a8fa 100644
--- a/sys/powerpc/conf/MPC85XX
+++ b/sys/powerpc/conf/MPC85XX
@@ -75,12 +75,15 @@ device alc
device ether
device fxp
device gpio
+device gpiopower
device iic
device iicbus
#device isa
device loop
device md
device miibus
+device mmc
+device mmcsd
device pass
device pci
device quicc
diff --git a/sys/powerpc/conf/MPC85XXSPE b/sys/powerpc/conf/MPC85XXSPE
index 15470d578bef..f9a0bc982ab6 100644
--- a/sys/powerpc/conf/MPC85XXSPE
+++ b/sys/powerpc/conf/MPC85XXSPE
@@ -75,12 +75,15 @@ device alc
device ether
device fxp
device gpio
+device gpiopower
device iic
device iicbus
#device isa
device loop
device md
device miibus
+device mmc
+device mmcsd
device pass
device pci
device quicc
@@ -88,6 +91,7 @@ device random
#device rl
device scbus
device scc
+device sdhci
device sec
device tsec
device dpaa
diff --git a/sys/powerpc/conf/dpaa/files.dpaa b/sys/powerpc/conf/dpaa/files.dpaa
index 18c44f9df91a..b4a6c1aa29bb 100644
--- a/sys/powerpc/conf/dpaa/files.dpaa
+++ b/sys/powerpc/conf/dpaa/files.dpaa
@@ -69,8 +69,6 @@ contrib/ncsw/user/env/core.c optional dpaa \
no-depend compile-with "${DPAA_COMPILE_CMD}"
# FreeBSD Wrappers
-dev/dpaa/dpaa.c optional dpaa fdt \
- no-depend compile-with "${DPAA_COMPILE_CMD}"
dev/dpaa/portals_common.c optional dpaa \
no-depend compile-with "${DPAA_COMPILE_CMD}"
dev/dpaa/bman_portals.c optional dpaa fdt \
diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h
index c6b819804b3a..c6611233960f 100644
--- a/sys/powerpc/include/pmap.h
+++ b/sys/powerpc/include/pmap.h
@@ -179,7 +179,7 @@ void slb_free_tree(pmap_t pm);
struct slb **slb_alloc_user_cache(void);
void slb_free_user_cache(struct slb **);
-#else
+#elif defined(BOOKE)
struct pmap {
struct mtx pm_mtx; /* pmap mutex */
@@ -204,6 +204,7 @@ typedef struct pv_entry *pv_entry_t;
struct md_page {
TAILQ_HEAD(, pv_entry) pv_list;
+ int pv_tracked;
};
#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT
@@ -261,6 +262,7 @@ extern int pmap_bootstrapped;
vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size);
void pmap_early_io_unmap(vm_offset_t va, vm_size_t size);
+void pmap_track_page(pmap_t pmap, vm_offset_t va);
#endif
diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h
index 697533b40af7..dd1f9b52ddbc 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.h
+++ b/sys/powerpc/mpc85xx/mpc85xx.h
@@ -36,6 +36,8 @@
* Configuration control and status registers
*/
extern vm_offset_t ccsrbar_va;
+extern vm_paddr_t ccsrbar_pa;
+extern vm_size_t ccsrbar_size;
#define CCSRBAR_VA ccsrbar_va
#define OCP85XX_CCSRBAR (CCSRBAR_VA + 0x0)
#define OCP85XX_BPTR (CCSRBAR_VA + 0x20)
diff --git a/sys/powerpc/mpc85xx/platform_mpc85xx.c b/sys/powerpc/mpc85xx/platform_mpc85xx.c
index 592fe961efd8..39309f5271f5 100644
--- a/sys/powerpc/mpc85xx/platform_mpc85xx.c
+++ b/sys/powerpc/mpc85xx/platform_mpc85xx.c
@@ -78,7 +78,9 @@ struct cpu_release {
#endif
extern uint32_t *bootinfo;
+vm_paddr_t ccsrbar_pa;
vm_offset_t ccsrbar_va;
+vm_size_t ccsrbar_size;
static int cpu, maxcpu;
@@ -194,6 +196,8 @@ mpc85xx_attach(platform_t plat)
ccsrsize |= ranges[i];
}
ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize);
+ ccsrbar_pa = ccsrbar;
+ ccsrbar_size = ccsrsize;
#if 0
mpc85xx_fix_errata(ccsrbar_va);
diff --git a/sys/powerpc/mpc85xx/qoriq_gpio.c b/sys/powerpc/mpc85xx/qoriq_gpio.c
index d09719cc3875..15e0a2cd325d 100644
--- a/sys/powerpc/mpc85xx/qoriq_gpio.c
+++ b/sys/powerpc/mpc85xx/qoriq_gpio.c
@@ -173,7 +173,7 @@ qoriq_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
outvals = bus_read_4(sc->sc_mem, GPIO_GPDAT);
outvals &= ~(1 << pinbit);
outvals |= (value << pinbit);
- bus_write_4(sc->sc_mem, 0, outvals);
+ bus_write_4(sc->sc_mem, GPIO_GPDAT, outvals);
GPIO_UNLOCK(sc);
@@ -208,7 +208,7 @@ qoriq_gpio_pin_toggle(device_t dev, uint32_t pin)
val = bus_read_4(sc->sc_mem, GPIO_GPDAT);
val ^= (1 << (31 - pin));
- bus_write_4(sc->sc_mem, 0, val);
+ bus_write_4(sc->sc_mem, GPIO_GPDAT, val);
GPIO_UNLOCK(sc);
diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC
index ad23c6647e73..a9c3c6fbdad0 100644
--- a/sys/riscv/conf/GENERIC
+++ b/sys/riscv/conf/GENERIC
@@ -69,7 +69,7 @@ options CAPABILITIES # Capsicum capabilities
options MAC # TrustedBSD MAC Framework
options KDTRACE_FRAME # Ensure frames are compiled in
options KDTRACE_HOOKS # Kernel DTrace hooks
-# options VFP # Floating-point support
+options FPE # Floating-point extension support
options RACCT # Resource accounting framework
options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
options RCTL # Resource limits
diff --git a/sys/arm/rockchip/rk30xx_common.c b/sys/riscv/include/fpe.h
index 826ebda79817..1294ab0de8fa 100644
--- a/sys/arm/rockchip/rk30xx_common.c
+++ b/sys/riscv/include/fpe.h
@@ -1,7 +1,11 @@
/*-
- * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@freebsd.org>
+ * Copyright (c) 2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -22,40 +26,13 @@
* 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 <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-
-#include <dev/fdt/fdt_common.h>
-#include <dev/ofw/openfirm.h>
-
-#include <machine/bus.h>
-#include <machine/vmparam.h>
-
-#ifndef INTRNG
-static int
-fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
- int *pol)
-{
-
- if (!fdt_is_compatible(node, "arm,gic"))
- return (ENXIO);
-
- *interrupt = fdt32_to_cpu(intr[0]);
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
+#ifndef _MACHINE_FPE_H_
+#define _MACHINE_FPE_H_
- return (0);
-}
+void fpe_state_save(struct thread *td);
-fdt_pic_decode_t fdt_pic_table[] = {
- &fdt_aintc_decode_ic,
- NULL
-};
-#endif
+#endif /* !_MACHINE_FPE_H_ */
diff --git a/sys/riscv/include/pcb.h b/sys/riscv/include/pcb.h
index a6cecb73434c..27737a4bdf24 100644
--- a/sys/riscv/include/pcb.h
+++ b/sys/riscv/include/pcb.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@@ -42,16 +42,21 @@
struct trapframe;
struct pcb {
- uint64_t pcb_ra;
- uint64_t pcb_sp;
- uint64_t pcb_gp;
- uint64_t pcb_tp;
- uint64_t pcb_t[7];
- uint64_t pcb_s[12];
- uint64_t pcb_a[8];
- uint64_t pcb_sepc;
+ uint64_t pcb_ra; /* Return address */
+ uint64_t pcb_sp; /* Stack pointer */
+ uint64_t pcb_gp; /* Global pointer */
+ uint64_t pcb_tp; /* Thread pointer */
+ uint64_t pcb_t[7]; /* Temporary registers */
+ uint64_t pcb_s[12]; /* Saved registers */
+ uint64_t pcb_a[8]; /* Argument registers */
+ uint64_t pcb_x[32][2]; /* Floating point registers */
+ uint64_t pcb_fcsr; /* Floating point control reg */
+ uint64_t pcb_fpflags; /* Floating point flags */
+#define PCB_FP_STARTED 0x1
+#define PCB_FP_USERMASK 0x1
+ uint64_t pcb_sepc; /* Supervisor exception pc */
vm_offset_t pcb_l1addr; /* L1 page tables base address */
- vm_offset_t pcb_onfault;
+ vm_offset_t pcb_onfault; /* Copyinout fault handler */
};
#ifdef _KERNEL
diff --git a/sys/riscv/include/reg.h b/sys/riscv/include/reg.h
index 35d79f10a8f5..9e94b4a5768d 100644
--- a/sys/riscv/include/reg.h
+++ b/sys/riscv/include/reg.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@@ -50,7 +50,8 @@ struct reg {
};
struct fpreg {
- int dummy;
+ uint64_t fp_x[32][2]; /* Floating point registers */
+ uint64_t fp_fcsr; /* Floating point control reg */
};
struct dbreg {
diff --git a/sys/riscv/include/riscvreg.h b/sys/riscv/include/riscvreg.h
index 2e3a4a2e9f5d..77f35bfa64b0 100644
--- a/sys/riscv/include/riscvreg.h
+++ b/sys/riscv/include/riscvreg.h
@@ -60,10 +60,14 @@
#define SSTATUS_SPIE_SHIFT 5
#define SSTATUS_SPP (1 << 8)
#define SSTATUS_SPP_SHIFT 8
-#define SSTATUS_FS_MASK 0x3
#define SSTATUS_FS_SHIFT 13
-#define SSTATUS_XS_MASK 0x3
+#define SSTATUS_FS_OFF (0x0 << SSTATUS_FS_SHIFT)
+#define SSTATUS_FS_INITIAL (0x1 << SSTATUS_FS_SHIFT)
+#define SSTATUS_FS_CLEAN (0x2 << SSTATUS_FS_SHIFT)
+#define SSTATUS_FS_DIRTY (0x3 << SSTATUS_FS_SHIFT)
+#define SSTATUS_FS_MASK (0x3 << SSTATUS_FS_SHIFT)
#define SSTATUS_XS_SHIFT 15
+#define SSTATUS_XS_MASK (0x3 << SSTATUS_XS_SHIFT)
#define SSTATUS_PUM (1 << 18)
#define SSTATUS32_SD (1 << 63)
#define SSTATUS64_SD (1 << 31)
diff --git a/sys/riscv/riscv/genassym.c b/sys/riscv/riscv/genassym.c
index c9e9bc1c991a..33f1d41750a7 100644
--- a/sys/riscv/riscv/genassym.c
+++ b/sys/riscv/riscv/genassym.c
@@ -72,6 +72,8 @@ ASSYM(PCB_TP, offsetof(struct pcb, pcb_tp));
ASSYM(PCB_T, offsetof(struct pcb, pcb_t));
ASSYM(PCB_S, offsetof(struct pcb, pcb_s));
ASSYM(PCB_A, offsetof(struct pcb, pcb_a));
+ASSYM(PCB_X, offsetof(struct pcb, pcb_x));
+ASSYM(PCB_FCSR, offsetof(struct pcb, pcb_fcsr));
ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c
index 7bc4402597de..f08527a7f2f3 100644
--- a/sys/riscv/riscv/machdep.c
+++ b/sys/riscv/riscv/machdep.c
@@ -84,8 +84,8 @@ __FBSDID("$FreeBSD$");
#include <machine/asm.h>
-#ifdef VFP
-#include <machine/vfp.h>
+#ifdef FPE
+#include <machine/fpe.h>
#endif
#ifdef FDT
@@ -203,17 +203,39 @@ set_regs(struct thread *td, struct reg *regs)
int
fill_fpregs(struct thread *td, struct fpreg *regs)
{
+#ifdef FPE
+ struct pcb *pcb;
+
+ pcb = td->td_pcb;
+
+ if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
+ /*
+ * If we have just been running FPE instructions we will
+ * need to save the state to memcpy it below.
+ */
+ fpe_state_save(td);
+
+ memcpy(regs->fp_x, pcb->pcb_x, sizeof(regs->fp_x));
+ regs->fp_fcsr = pcb->pcb_fcsr;
+ } else
+#endif
+ memset(regs->fp_x, 0, sizeof(regs->fp_x));
- /* TODO */
- bzero(regs, sizeof(*regs));
return (0);
}
int
set_fpregs(struct thread *td, struct fpreg *regs)
{
+#ifdef FPE
+ struct pcb *pcb;
+
+ pcb = td->td_pcb;
+
+ memcpy(pcb->pcb_x, regs->fp_x, sizeof(regs->fp_x));
+ pcb->pcb_fcsr = regs->fp_fcsr;
+#endif
- /* TODO */
return (0);
}
@@ -259,8 +281,10 @@ void
exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
{
struct trapframe *tf;
+ struct pcb *pcb;
tf = td->td_frame;
+ pcb = td->td_pcb;
memset(tf, 0, sizeof(struct trapframe));
@@ -273,6 +297,8 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
tf->tf_sp = STACKALIGN(stack);
tf->tf_ra = imgp->entry_addr;
tf->tf_sepc = imgp->entry_addr;
+
+ pcb->pcb_fpflags &= ~PCB_FP_STARTED;
}
/* Sanity check these are the same size, they will be memcpy'd to and fro */
@@ -337,13 +363,54 @@ set_mcontext(struct thread *td, mcontext_t *mcp)
static void
get_fpcontext(struct thread *td, mcontext_t *mcp)
{
- /* TODO */
+#ifdef FPE
+ struct pcb *curpcb;
+
+ critical_enter();
+
+ curpcb = curthread->td_pcb;
+
+ KASSERT(td->td_pcb == curpcb, ("Invalid fpe pcb"));
+
+ if ((curpcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
+ /*
+ * If we have just been running FPE instructions we will
+ * need to save the state to memcpy it below.
+ */
+ fpe_state_save(td);
+
+ KASSERT((curpcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
+ ("Non-userspace FPE flags set in get_fpcontext"));
+ memcpy(mcp->mc_fpregs.fp_x, curpcb->pcb_x,
+ sizeof(mcp->mc_fpregs));
+ mcp->mc_fpregs.fp_fcsr = curpcb->pcb_fcsr;
+ mcp->mc_fpregs.fp_flags = curpcb->pcb_fpflags;
+ mcp->mc_flags |= _MC_FP_VALID;
+ }
+
+ critical_exit();
+#endif
}
static void
set_fpcontext(struct thread *td, mcontext_t *mcp)
{
- /* TODO */
+#ifdef FPE
+ struct pcb *curpcb;
+
+ critical_enter();
+
+ if ((mcp->mc_flags & _MC_FP_VALID) != 0) {
+ curpcb = curthread->td_pcb;
+ /* FPE usage is enabled, override registers. */
+ memcpy(curpcb->pcb_x, mcp->mc_fpregs.fp_x,
+ sizeof(mcp->mc_fpregs));
+ curpcb->pcb_fcsr = mcp->mc_fpregs.fp_fcsr;
+ curpcb->pcb_fpflags = mcp->mc_fpregs.fp_flags & PCB_FP_USERMASK;
+ }
+
+ critical_exit();
+#endif
}
void
@@ -572,6 +639,7 @@ init_proc0(vm_offset_t kstack)
proc_linkup0(&proc0, &thread0);
thread0.td_kstack = kstack;
thread0.td_pcb = (struct pcb *)(thread0.td_kstack) - 1;
+ thread0.td_pcb->pcb_fpflags = 0;
thread0.td_frame = &proc0_tf;
pcpup->pc_curpcb = thread0.td_pcb;
}
diff --git a/sys/riscv/riscv/mp_machdep.c b/sys/riscv/riscv/mp_machdep.c
index 33353ac2a3c8..adad7b4b533b 100644
--- a/sys/riscv/riscv/mp_machdep.c
+++ b/sys/riscv/riscv/mp_machdep.c
@@ -62,9 +62,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/smp.h>
#include <machine/sbi.h>
-#ifdef VFP
-#include <machine/vfp.h>
-#endif
#ifdef FDT
#include <dev/ofw/openfirm.h>
@@ -242,10 +239,6 @@ init_secondary(uint64_t cpu)
/* Start per-CPU event timers. */
cpu_initclocks_ap();
-#ifdef VFP
- /* TODO: init FPU */
-#endif
-
/* Enable interrupts */
intr_enable();
diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c
index 472779c35ad7..af8806d8eead 100644
--- a/sys/riscv/riscv/pmap.c
+++ b/sys/riscv/riscv/pmap.c
@@ -1992,6 +1992,8 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
l2 = pmap_l1_to_l2(l1, sva);
if (l2 == NULL)
continue;
+ if (pmap_load(l2) == 0)
+ continue;
if ((pmap_load(l2) & PTE_RX) != 0)
continue;
diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S
index b5cced30d8f7..5cc1edd69a02 100644
--- a/sys/riscv/riscv/swtch.S
+++ b/sys/riscv/riscv/swtch.S
@@ -42,6 +42,117 @@
__FBSDID("$FreeBSD$");
+#ifdef FPE
+.macro __fpe_state_save p
+ /*
+ * Enable FPE usage in supervisor mode,
+ * so we can access registers.
+ */
+ li t0, SSTATUS_FS_INITIAL
+ csrs sstatus, t0
+
+ /* Store registers */
+ frcsr t0
+ sd t0, (PCB_FCSR)(\p)
+ fsd f0, (PCB_X + 0 * 16)(\p)
+ fsd f1, (PCB_X + 1 * 16)(\p)
+ fsd f2, (PCB_X + 2 * 16)(\p)
+ fsd f3, (PCB_X + 3 * 16)(\p)
+ fsd f4, (PCB_X + 4 * 16)(\p)
+ fsd f5, (PCB_X + 5 * 16)(\p)
+ fsd f6, (PCB_X + 6 * 16)(\p)
+ fsd f7, (PCB_X + 7 * 16)(\p)
+ fsd f8, (PCB_X + 8 * 16)(\p)
+ fsd f9, (PCB_X + 9 * 16)(\p)
+ fsd f10, (PCB_X + 10 * 16)(\p)
+ fsd f11, (PCB_X + 11 * 16)(\p)
+ fsd f12, (PCB_X + 12 * 16)(\p)
+ fsd f13, (PCB_X + 13 * 16)(\p)
+ fsd f14, (PCB_X + 14 * 16)(\p)
+ fsd f15, (PCB_X + 15 * 16)(\p)
+ fsd f16, (PCB_X + 16 * 16)(\p)
+ fsd f17, (PCB_X + 17 * 16)(\p)
+ fsd f18, (PCB_X + 18 * 16)(\p)
+ fsd f19, (PCB_X + 19 * 16)(\p)
+ fsd f20, (PCB_X + 20 * 16)(\p)
+ fsd f21, (PCB_X + 21 * 16)(\p)
+ fsd f22, (PCB_X + 22 * 16)(\p)
+ fsd f23, (PCB_X + 23 * 16)(\p)
+ fsd f24, (PCB_X + 24 * 16)(\p)
+ fsd f25, (PCB_X + 25 * 16)(\p)
+ fsd f26, (PCB_X + 26 * 16)(\p)
+ fsd f27, (PCB_X + 27 * 16)(\p)
+ fsd f28, (PCB_X + 28 * 16)(\p)
+ fsd f29, (PCB_X + 29 * 16)(\p)
+ fsd f30, (PCB_X + 30 * 16)(\p)
+ fsd f31, (PCB_X + 31 * 16)(\p)
+
+ /* Disable FPE usage in supervisor mode. */
+ li t0, SSTATUS_FS_MASK
+ csrc sstatus, t0
+.endm
+
+.macro __fpe_state_load p
+ /*
+ * Enable FPE usage in supervisor mode,
+ * so we can access registers.
+ */
+ li t0, SSTATUS_FS_INITIAL
+ csrs sstatus, t0
+
+ /* Restore registers */
+ ld t0, (PCB_FCSR)(\p)
+ fscsr t0
+ fld f0, (PCB_X + 0 * 16)(\p)
+ fld f1, (PCB_X + 1 * 16)(\p)
+ fld f2, (PCB_X + 2 * 16)(\p)
+ fld f3, (PCB_X + 3 * 16)(\p)
+ fld f4, (PCB_X + 4 * 16)(\p)
+ fld f5, (PCB_X + 5 * 16)(\p)
+ fld f6, (PCB_X + 6 * 16)(\p)
+ fld f7, (PCB_X + 7 * 16)(\p)
+ fld f8, (PCB_X + 8 * 16)(\p)
+ fld f9, (PCB_X + 9 * 16)(\p)
+ fld f10, (PCB_X + 10 * 16)(\p)
+ fld f11, (PCB_X + 11 * 16)(\p)
+ fld f12, (PCB_X + 12 * 16)(\p)
+ fld f13, (PCB_X + 13 * 16)(\p)
+ fld f14, (PCB_X + 14 * 16)(\p)
+ fld f15, (PCB_X + 15 * 16)(\p)
+ fld f16, (PCB_X + 16 * 16)(\p)
+ fld f17, (PCB_X + 17 * 16)(\p)
+ fld f18, (PCB_X + 18 * 16)(\p)
+ fld f19, (PCB_X + 19 * 16)(\p)
+ fld f20, (PCB_X + 20 * 16)(\p)
+ fld f21, (PCB_X + 21 * 16)(\p)
+ fld f22, (PCB_X + 22 * 16)(\p)
+ fld f23, (PCB_X + 23 * 16)(\p)
+ fld f24, (PCB_X + 24 * 16)(\p)
+ fld f25, (PCB_X + 25 * 16)(\p)
+ fld f26, (PCB_X + 26 * 16)(\p)
+ fld f27, (PCB_X + 27 * 16)(\p)
+ fld f28, (PCB_X + 28 * 16)(\p)
+ fld f29, (PCB_X + 29 * 16)(\p)
+ fld f30, (PCB_X + 30 * 16)(\p)
+ fld f31, (PCB_X + 31 * 16)(\p)
+
+ /* Disable FPE usage in supervisor mode. */
+ li t0, SSTATUS_FS_MASK
+ csrc sstatus, t0
+.endm
+
+/*
+ * void
+ * fpe_state_save(struct thread *td)
+ */
+ENTRY(fpe_state_save)
+ /* Get pointer to PCB */
+ ld a0, TD_PCB(a0)
+ __fpe_state_save a0
+ ret
+END(fpe_state_save)
+#endif /* FPE */
+
/*
* void cpu_throw(struct thread *old, struct thread *new)
*/
@@ -81,8 +192,20 @@ ENTRY(cpu_throw)
ld s10, (PCB_S + 10 * 8)(x13)
ld s11, (PCB_S + 11 * 8)(x13)
- ret
+#ifdef FPE
+ /* Is FPE enabled for new thread? */
+ ld t0, TD_FRAME(a1)
+ ld t1, (TF_SSTATUS)(t0)
+ li t2, SSTATUS_FS_MASK
+ and t3, t1, t2
+ beqz t3, 1f /* No, skip. */
+
+ /* Restore registers. */
+ __fpe_state_load x13
+1:
+#endif
+ ret
.Lcpu_throw_panic_str:
.asciz "cpu_throw: %p\0"
END(cpu_throw)
@@ -123,6 +246,29 @@ ENTRY(cpu_switch)
sd s10, (PCB_S + 10 * 8)(x13)
sd s11, (PCB_S + 11 * 8)(x13)
+#ifdef FPE
+ /*
+ * Is FPE enabled and is it in dirty state
+ * for the old thread?
+ */
+ ld t0, TD_FRAME(a0)
+ ld t1, (TF_SSTATUS)(t0)
+ li t2, SSTATUS_FS_MASK
+ and t3, t1, t2
+ li t2, SSTATUS_FS_DIRTY
+ bne t3, t2, 1f /* No, skip. */
+
+ /* Yes, mark FPE state clean and save registers. */
+ li t2, ~SSTATUS_FS_MASK
+ and t3, t1, t2
+ li t2, SSTATUS_FS_CLEAN
+ or t3, t3, t2
+ sd t3, (TF_SSTATUS)(t0)
+
+ __fpe_state_save x13
+1:
+#endif
+
/*
* Restore the saved context.
*/
@@ -171,6 +317,20 @@ ENTRY(cpu_switch)
ld s9, (PCB_S + 9 * 8)(x13)
ld s10, (PCB_S + 10 * 8)(x13)
ld s11, (PCB_S + 11 * 8)(x13)
+
+#ifdef FPE
+ /* Is FPE enabled for new thread? */
+ ld t0, TD_FRAME(a1)
+ ld t1, (TF_SSTATUS)(t0)
+ li t2, SSTATUS_FS_MASK
+ and t3, t1, t2
+ beqz t3, 1f /* No, skip. */
+
+ /* Restore registers. */
+ __fpe_state_load x13
+1:
+#endif
+
ret
.Lcpu_switch_panic_str:
.asciz "cpu_switch: %p\0"
@@ -269,9 +429,8 @@ ENTRY(savectx)
sd s10, (PCB_S + 10 * 8)(a0)
sd s11, (PCB_S + 11 * 8)(a0)
- /* Store the VFP registers */
-#ifdef VFP
- /* TODO */
+#ifdef FPE
+ __fpe_state_save a0
#endif
ret
END(savectx)
diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c
index 97d9a2c1efdd..cd2b7c4bfb74 100644
--- a/sys/riscv/riscv/trap.c
+++ b/sys/riscv/riscv/trap.c
@@ -328,9 +328,11 @@ do_trap_user(struct trapframe *frame)
uint64_t exception;
struct thread *td;
uint64_t sstatus;
+ struct pcb *pcb;
td = curthread;
td->td_frame = frame;
+ pcb = td->td_pcb;
/* Ensure we came from usermode, interrupts disabled */
__asm __volatile("csrr %0, sstatus" : "=&r" (sstatus));
@@ -358,6 +360,17 @@ do_trap_user(struct trapframe *frame)
svc_handler(frame);
break;
case EXCP_ILLEGAL_INSTRUCTION:
+#ifdef FPE
+ if ((pcb->pcb_fpflags & PCB_FP_STARTED) == 0) {
+ /*
+ * May be a FPE trap. Enable FPE usage
+ * for this thread and try again.
+ */
+ frame->tf_sstatus |= SSTATUS_FS_INITIAL;
+ pcb->pcb_fpflags |= PCB_FP_STARTED;
+ break;
+ }
+#endif
call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)frame->tf_sepc);
userret(td, frame);
break;
diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c
index d2d4c6e3d3ec..c5c62fe24db2 100644
--- a/sys/riscv/riscv/vm_machdep.c
+++ b/sys/riscv/riscv/vm_machdep.c
@@ -87,8 +87,8 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
/* Arguments for child */
tf->tf_a[0] = 0;
tf->tf_a[1] = 0;
- tf->tf_sstatus = (SSTATUS_SPIE);
- tf->tf_sstatus |= (MSTATUS_PRV_U << MSTATUS_SPP_SHIFT);
+ tf->tf_sstatus |= (SSTATUS_SPIE); /* Enable interrupts. */
+ tf->tf_sstatus &= ~(SSTATUS_SPP); /* User mode. */
td2->td_frame = tf;
diff --git a/sys/sys/kerneldump.h b/sys/sys/kerneldump.h
index fd010181eb1d..13bef698ffcb 100644
--- a/sys/sys/kerneldump.h
+++ b/sys/sys/kerneldump.h
@@ -64,7 +64,8 @@ struct kerneldumpheader {
#define KERNELDUMPMAGIC_CLEARED "Cleared Kernel Dump"
char architecture[12];
uint32_t version;
-#define KERNELDUMPVERSION 1
+#define KERNELDUMPVERSION 1
+#define KERNELDUMP_TEXT_VERSION 1
uint32_t architectureversion;
#define KERNELDUMP_AARCH64_VERSION 1
#define KERNELDUMP_AMD64_VERSION 2
@@ -74,7 +75,6 @@ struct kerneldumpheader {
#define KERNELDUMP_POWERPC_VERSION 1
#define KERNELDUMP_RISCV_VERSION 1
#define KERNELDUMP_SPARC64_VERSION 1
-#define KERNELDUMP_TEXT_VERSION 1
uint64_t dumplength; /* excl headers */
uint64_t dumptime;
uint32_t blocksize;
diff --git a/sys/sys/queue.h b/sys/sys/queue.h
index 7bb604f3de2b..cff8fabd7f6e 100644
--- a/sys/sys/queue.h
+++ b/sys/sys/queue.h
@@ -472,6 +472,12 @@ struct { \
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
+/*
+ * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME)
+ *
+ * If the list is non-empty, validates that the first element of the list
+ * points back at 'head.'
+ */
#define QMD_LIST_CHECK_HEAD(head, field) do { \
if (LIST_FIRST((head)) != NULL && \
LIST_FIRST((head))->field.le_prev != \
@@ -479,6 +485,12 @@ struct { \
panic("Bad list head %p first->prev != head", (head)); \
} while (0)
+/*
+ * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME)
+ *
+ * If an element follows 'elm' in the list, validates that the next element
+ * points back at 'elm.'
+ */
#define QMD_LIST_CHECK_NEXT(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL && \
LIST_NEXT((elm), field)->field.le_prev != \
@@ -486,6 +498,11 @@ struct { \
panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0)
+/*
+ * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME)
+ *
+ * Validates that the previous element (or head of the list) points to 'elm.'
+ */
#define QMD_LIST_CHECK_PREV(elm, field) do { \
if (*(elm)->field.le_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \
@@ -634,6 +651,12 @@ struct { \
* Tail queue functions.
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
+/*
+ * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME)
+ *
+ * If the tailq is non-empty, validates that the first element of the tailq
+ * points back at 'head.'
+ */
#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
if (!TAILQ_EMPTY(head) && \
TAILQ_FIRST((head))->field.tqe_prev != \
@@ -641,11 +664,22 @@ struct { \
panic("Bad tailq head %p first->prev != head", (head)); \
} while (0)
+/*
+ * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME)
+ *
+ * Validates that the tail of the tailq is a pointer to pointer to NULL.
+ */
#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
if (*(head)->tqh_last != NULL) \
panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
} while (0)
+/*
+ * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME)
+ *
+ * If an element follows 'elm' in the tailq, validates that the next element
+ * points back at 'elm.'
+ */
#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
if (TAILQ_NEXT((elm), field) != NULL && \
TAILQ_NEXT((elm), field)->field.tqe_prev != \
@@ -653,6 +687,11 @@ struct { \
panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0)
+/*
+ * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME)
+ *
+ * Validates that the previous element (or head of the tailq) points to 'elm.'
+ */
#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
if (*(elm)->field.tqe_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \
diff --git a/sys/sys/sf_buf.h b/sys/sys/sf_buf.h
index b5970d95fd82..6aebe430ab69 100644
--- a/sys/sys/sf_buf.h
+++ b/sys/sys/sf_buf.h
@@ -41,6 +41,7 @@ struct sfstat { /* sendfile statistics */
uint64_t sf_busy; /* times aborted on a busy page */
uint64_t sf_allocfail; /* times sfbuf allocation failed */
uint64_t sf_allocwait; /* times sfbuf allocation had to wait */
+ uint64_t sf_pages_bogus; /* times bogus page was used */
};
#ifdef _KERNEL
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index f23b5f6994c2..ea3d9b6bee34 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -590,6 +590,7 @@ struct sf_hdtr {
#define SF_NODISKIO 0x00000001
#define SF_MNOWAIT 0x00000002 /* obsolete */
#define SF_SYNC 0x00000004
+#define SF_USER_READAHEAD 0x00000008
#define SF_NOCACHE 0x00000010
#define SF_FLAGS(rh, flags) (((rh) << 16) | (flags))
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 2520f007ec6e..c258a202920d 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -147,7 +147,7 @@ ffs_mount(struct mount *mp)
struct ufsmount *ump = NULL;
struct fs *fs;
pid_t fsckpid = 0;
- int error, flags;
+ int error, error1, flags;
uint64_t mntorflags;
accmode_t accmode;
struct nameidata ndp;
@@ -453,6 +453,11 @@ ffs_mount(struct mount *mp)
*/
if (mp->mnt_flag & MNT_SNAPSHOT)
return (ffs_snapshot(mp, fspec));
+
+ /*
+ * Must not call namei() while owning busy ref.
+ */
+ vfs_unbusy(mp);
}
/*
@@ -460,7 +465,18 @@ ffs_mount(struct mount *mp)
* and verify that it refers to a sensible disk device.
*/
NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td);
- if ((error = namei(&ndp)) != 0)
+ error = namei(&ndp);
+ if ((mp->mnt_flag & MNT_UPDATE) != 0) {
+ /*
+ * Unmount does not start if MNT_UPDATE is set. Mount
+ * update busies mp before setting MNT_UPDATE. We
+ * must be able to retain our busy ref succesfully,
+ * without sleep.
+ */
+ error1 = vfs_busy(mp, MBF_NOWAIT);
+ MPASS(error1 == 0);
+ }
+ if (error != 0)
return (error);
NDFREE(&ndp, NDF_ONLY_PNBUF);
devvp = ndp.ni_vp;
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 8f46cf38e7bc..bf57203c119b 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -1126,7 +1126,7 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
if (shift != 0) {
for (i = 1; i <= shift; i++) {
p = vm_page_alloc(object, m[0]->pindex - i,
- VM_ALLOC_NORMAL | VM_ALLOC_IFNOTCACHED);
+ VM_ALLOC_NORMAL);
if (p == NULL) {
/* Shift allocated pages to the left. */
for (j = 0; j < i - 1; j++)
@@ -1144,8 +1144,7 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
if (rahead != NULL) {
for (i = 0; i < *rahead; i++) {
p = vm_page_alloc(object,
- m[reqcount - 1]->pindex + i + 1,
- VM_ALLOC_NORMAL | VM_ALLOC_IFNOTCACHED);
+ m[reqcount - 1]->pindex + i + 1, VM_ALLOC_NORMAL);
if (p == NULL)
break;
bp->b_pages[shift + reqcount + i] = p;
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index b73cf6459188..41391eb7e2b3 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -246,6 +246,48 @@ vm_fault_dirty(vm_map_entry_t entry, vm_page_t m, vm_prot_t prot,
vm_pager_page_unswapped(m);
}
+static void
+vm_fault_fill_hold(vm_page_t *m_hold, vm_page_t m)
+{
+
+ if (m_hold != NULL) {
+ *m_hold = m;
+ vm_page_lock(m);
+ vm_page_hold(m);
+ vm_page_unlock(m);
+ }
+}
+
+/*
+ * Unlocks fs.first_object and fs.map on success.
+ */
+static int
+vm_fault_soft_fast(struct faultstate *fs, vm_offset_t vaddr, vm_prot_t prot,
+ int fault_type, int fault_flags, boolean_t wired, vm_page_t *m_hold)
+{
+ vm_page_t m;
+ int rv;
+
+ MPASS(fs->vp == NULL);
+ m = vm_page_lookup(fs->first_object, fs->first_pindex);
+ /* A busy page can be mapped for read|execute access. */
+ if (m == NULL || ((prot & VM_PROT_WRITE) != 0 &&
+ vm_page_busied(m)) || m->valid != VM_PAGE_BITS_ALL)
+ return (KERN_FAILURE);
+ rv = pmap_enter(fs->map->pmap, vaddr, m, prot, fault_type |
+ PMAP_ENTER_NOSLEEP | (wired ? PMAP_ENTER_WIRED : 0), 0);
+ if (rv != KERN_SUCCESS)
+ return (rv);
+ vm_fault_fill_hold(m_hold, m);
+ vm_fault_dirty(fs->entry, m, prot, fault_type, fault_flags, false);
+ VM_OBJECT_RUNLOCK(fs->first_object);
+ if (!wired)
+ vm_fault_prefault(fs, vaddr, PFBAK, PFFOR);
+ vm_map_lookup_done(fs->map, fs->entry);
+ curthread->td_ru.ru_minflt++;
+ return (KERN_SUCCESS);
+}
+
/*
* vm_fault:
*
@@ -294,7 +336,6 @@ vm_fault_hold(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
struct vnode *vp;
vm_object_t next_object, retry_object;
vm_offset_t e_end, e_start;
- vm_page_t m;
vm_pindex_t retry_pindex;
vm_prot_t prot, retry_prot;
int ahead, alloc_req, behind, cluster_offset, error, era, faultcount;
@@ -376,36 +417,15 @@ RetryFault:;
(fs.first_object->flags & OBJ_TMPFS_NODE) == 0) ||
(fs.first_object->flags & OBJ_MIGHTBEDIRTY) != 0)) {
VM_OBJECT_RLOCK(fs.first_object);
- if ((prot & VM_PROT_WRITE) != 0 &&
- (fs.first_object->type == OBJT_VNODE ||
- (fs.first_object->flags & OBJ_TMPFS_NODE) != 0) &&
- (fs.first_object->flags & OBJ_MIGHTBEDIRTY) == 0)
- goto fast_failed;
- m = vm_page_lookup(fs.first_object, fs.first_pindex);
- /* A busy page can be mapped for read|execute access. */
- if (m == NULL || ((prot & VM_PROT_WRITE) != 0 &&
- vm_page_busied(m)) || m->valid != VM_PAGE_BITS_ALL)
- goto fast_failed;
- result = pmap_enter(fs.map->pmap, vaddr, m, prot,
- fault_type | PMAP_ENTER_NOSLEEP | (wired ? PMAP_ENTER_WIRED :
- 0), 0);
- if (result != KERN_SUCCESS)
- goto fast_failed;
- if (m_hold != NULL) {
- *m_hold = m;
- vm_page_lock(m);
- vm_page_hold(m);
- vm_page_unlock(m);
+ if ((prot & VM_PROT_WRITE) == 0 ||
+ (fs.first_object->type != OBJT_VNODE &&
+ (fs.first_object->flags & OBJ_TMPFS_NODE) == 0) ||
+ (fs.first_object->flags & OBJ_MIGHTBEDIRTY) != 0) {
+ rv = vm_fault_soft_fast(&fs, vaddr, prot, fault_type,
+ fault_flags, wired, m_hold);
+ if (rv == KERN_SUCCESS)
+ return (rv);
}
- vm_fault_dirty(fs.entry, m, prot, fault_type, fault_flags,
- false);
- VM_OBJECT_RUNLOCK(fs.first_object);
- if (!wired)
- vm_fault_prefault(&fs, vaddr, PFBAK, PFFOR);
- vm_map_lookup_done(fs.map, fs.entry);
- curthread->td_ru.ru_minflt++;
- return (KERN_SUCCESS);
-fast_failed:
if (!VM_OBJECT_TRYUPGRADE(fs.first_object)) {
VM_OBJECT_RUNLOCK(fs.first_object);
VM_OBJECT_WLOCK(fs.first_object);
@@ -559,8 +579,7 @@ fast_failed:
unlock_and_deallocate(&fs);
VM_WAITPFAULT;
goto RetryFault;
- } else if (fs.m->valid == VM_PAGE_BITS_ALL)
- break;
+ }
}
readrest:
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index 1fd97d1f5aa5..be84ec2167ef 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -877,9 +877,6 @@ RestartScan:
pindex = OFF_TO_IDX(current->offset +
(addr - current->start));
m = vm_page_lookup(object, pindex);
- if (m == NULL &&
- vm_page_is_cached(object, pindex))
- mincoreinfo = MINCORE_INCORE;
if (m != NULL && m->valid == 0)
m = NULL;
if (m != NULL)
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 0cf364fcaa47..676a6971f321 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -178,9 +178,6 @@ vm_object_zdtor(void *mem, int size, void *arg)
("object %p has reservations",
object));
#endif
- KASSERT(vm_object_cache_is_empty(object),
- ("object %p has cached pages",
- object));
KASSERT(object->paging_in_progress == 0,
("object %p paging_in_progress = %d",
object, object->paging_in_progress));
@@ -212,8 +209,6 @@ vm_object_zinit(void *mem, int size, int flags)
object->paging_in_progress = 0;
object->resident_page_count = 0;
object->shadow_count = 0;
- object->cache.rt_root = 0;
- object->cache.rt_flags = 0;
mtx_lock(&vm_object_list_mtx);
TAILQ_INSERT_TAIL(&vm_object_list, object, object_list);
@@ -792,8 +787,6 @@ vm_object_terminate(vm_object_t object)
if (__predict_false(!LIST_EMPTY(&object->rvq)))
vm_reserv_break_all(object);
#endif
- if (__predict_false(!vm_object_cache_is_empty(object)))
- vm_page_cache_free(object, 0, 0);
KASSERT(object->cred == NULL || object->type == OBJT_DEFAULT ||
object->type == OBJT_SWAP,
@@ -1135,13 +1128,6 @@ shadowlookup:
} else if ((tobject->flags & OBJ_UNMANAGED) != 0)
goto unlock_tobject;
m = vm_page_lookup(tobject, tpindex);
- if (m == NULL && advise == MADV_WILLNEED) {
- /*
- * If the page is cached, reactivate it.
- */
- m = vm_page_alloc(tobject, tpindex, VM_ALLOC_IFCACHED |
- VM_ALLOC_NOBUSY);
- }
if (m == NULL) {
/*
* There may be swap even if there is no backing page
@@ -1406,19 +1392,6 @@ retry:
swap_pager_copy(orig_object, new_object, offidxstart, 0);
TAILQ_FOREACH(m, &new_object->memq, listq)
vm_page_xunbusy(m);
-
- /*
- * Transfer any cached pages from orig_object to new_object.
- * If swap_pager_copy() found swapped out pages within the
- * specified range of orig_object, then it changed
- * new_object's type to OBJT_SWAP when it transferred those
- * pages to new_object. Otherwise, new_object's type
- * should still be OBJT_DEFAULT and orig_object should not
- * contain any cached pages within the specified range.
- */
- if (__predict_false(!vm_object_cache_is_empty(orig_object)))
- vm_page_cache_transfer(orig_object, offidxstart,
- new_object);
}
VM_OBJECT_WUNLOCK(orig_object);
VM_OBJECT_WUNLOCK(new_object);
@@ -1754,13 +1727,6 @@ vm_object_collapse(vm_object_t object)
backing_object,
object,
OFF_TO_IDX(object->backing_object_offset), TRUE);
-
- /*
- * Free any cached pages from backing_object.
- */
- if (__predict_false(
- !vm_object_cache_is_empty(backing_object)))
- vm_page_cache_free(backing_object, 0, 0);
}
/*
* Object now shadows whatever backing_object did.
@@ -1889,7 +1855,7 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end,
(options & (OBJPR_CLEANONLY | OBJPR_NOTMAPPED)) == OBJPR_NOTMAPPED,
("vm_object_page_remove: illegal options for object %p", object));
if (object->resident_page_count == 0)
- goto skipmemq;
+ return;
vm_object_pip_add(object, 1);
again:
p = vm_page_find_least(object, start);
@@ -1946,9 +1912,6 @@ next:
vm_page_unlock(p);
}
vm_object_pip_wakeup(object);
-skipmemq:
- if (__predict_false(!vm_object_cache_is_empty(object)))
- vm_page_cache_free(object, start, end);
}
/*
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index 73998aae8434..52bc44ce2b3b 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -118,7 +118,6 @@ struct vm_object {
vm_ooffset_t backing_object_offset;/* Offset in backing object */
TAILQ_ENTRY(vm_object) pager_object_list; /* list of all objects of this pager type */
LIST_HEAD(, vm_reserv) rvq; /* list of reservations */
- struct vm_radix cache; /* (o + f) root of the cache page radix trie */
void *handle;
union {
/*
@@ -290,13 +289,6 @@ void vm_object_pip_wakeup(vm_object_t object);
void vm_object_pip_wakeupn(vm_object_t object, short i);
void vm_object_pip_wait(vm_object_t object, char *waitid);
-static __inline boolean_t
-vm_object_cache_is_empty(vm_object_t object)
-{
-
- return (vm_radix_is_empty(&object->cache));
-}
-
void umtx_shm_object_init(vm_object_t object);
void umtx_shm_object_terminated(vm_object_t object);
extern int umtx_shm_vnobj_persistent;
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 78bf98ae0164..50c95bf5c404 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -154,8 +154,7 @@ static int vm_pageout_pages_needed;
static uma_zone_t fakepg_zone;
-static struct vnode *vm_page_alloc_init(vm_page_t m);
-static void vm_page_cache_turn_free(vm_page_t m);
+static void vm_page_alloc_check(vm_page_t m);
static void vm_page_clear_dirty_mask(vm_page_t m, vm_page_bits_t pagebits);
static void vm_page_enqueue(uint8_t queue, vm_page_t m);
static void vm_page_free_wakeup(void);
@@ -1118,9 +1117,7 @@ void
vm_page_dirty_KBI(vm_page_t m)
{
- /* These assertions refer to this operation by its public name. */
- KASSERT((m->flags & PG_CACHED) == 0,
- ("vm_page_dirty: page in cache!"));
+ /* Refer to this operation by its public name. */
KASSERT(m->valid == VM_PAGE_BITS_ALL,
("vm_page_dirty: page is invalid!"));
m->dirty = VM_PAGE_BITS_ALL;
@@ -1459,142 +1456,6 @@ vm_page_rename(vm_page_t m, vm_object_t new_object, vm_pindex_t new_pindex)
}
/*
- * Convert all of the given object's cached pages that have a
- * pindex within the given range into free pages. If the value
- * zero is given for "end", then the range's upper bound is
- * infinity. If the given object is backed by a vnode and it
- * transitions from having one or more cached pages to none, the
- * vnode's hold count is reduced.
- */
-void
-vm_page_cache_free(vm_object_t object, vm_pindex_t start, vm_pindex_t end)
-{
- vm_page_t m;
- boolean_t empty;
-
- mtx_lock(&vm_page_queue_free_mtx);
- if (__predict_false(vm_radix_is_empty(&object->cache))) {
- mtx_unlock(&vm_page_queue_free_mtx);
- return;
- }
- while ((m = vm_radix_lookup_ge(&object->cache, start)) != NULL) {
- if (end != 0 && m->pindex >= end)
- break;
- vm_radix_remove(&object->cache, m->pindex);
- vm_page_cache_turn_free(m);
- }
- empty = vm_radix_is_empty(&object->cache);
- mtx_unlock(&vm_page_queue_free_mtx);
- if (object->type == OBJT_VNODE && empty)
- vdrop(object->handle);
-}
-
-/*
- * Returns the cached page that is associated with the given
- * object and offset. If, however, none exists, returns NULL.
- *
- * The free page queue must be locked.
- */
-static inline vm_page_t
-vm_page_cache_lookup(vm_object_t object, vm_pindex_t pindex)
-{
-
- mtx_assert(&vm_page_queue_free_mtx, MA_OWNED);
- return (vm_radix_lookup(&object->cache, pindex));
-}
-
-/*
- * Remove the given cached page from its containing object's
- * collection of cached pages.
- *
- * The free page queue must be locked.
- */
-static void
-vm_page_cache_remove(vm_page_t m)
-{
-
- mtx_assert(&vm_page_queue_free_mtx, MA_OWNED);
- KASSERT((m->flags & PG_CACHED) != 0,
- ("vm_page_cache_remove: page %p is not cached", m));
- vm_radix_remove(&m->object->cache, m->pindex);
- m->object = NULL;
- vm_cnt.v_cache_count--;
-}
-
-/*
- * Transfer all of the cached pages with offset greater than or
- * equal to 'offidxstart' from the original object's cache to the
- * new object's cache. However, any cached pages with offset
- * greater than or equal to the new object's size are kept in the
- * original object. Initially, the new object's cache must be
- * empty. Offset 'offidxstart' in the original object must
- * correspond to offset zero in the new object.
- *
- * The new object must be locked.
- */
-void
-vm_page_cache_transfer(vm_object_t orig_object, vm_pindex_t offidxstart,
- vm_object_t new_object)
-{
- vm_page_t m;
-
- /*
- * Insertion into an object's collection of cached pages
- * requires the object to be locked. In contrast, removal does
- * not.
- */
- VM_OBJECT_ASSERT_WLOCKED(new_object);
- KASSERT(vm_radix_is_empty(&new_object->cache),
- ("vm_page_cache_transfer: object %p has cached pages",
- new_object));
- mtx_lock(&vm_page_queue_free_mtx);
- while ((m = vm_radix_lookup_ge(&orig_object->cache,
- offidxstart)) != NULL) {
- /*
- * Transfer all of the pages with offset greater than or
- * equal to 'offidxstart' from the original object's
- * cache to the new object's cache.
- */
- if ((m->pindex - offidxstart) >= new_object->size)
- break;
- vm_radix_remove(&orig_object->cache, m->pindex);
- /* Update the page's object and offset. */
- m->object = new_object;
- m->pindex -= offidxstart;
- if (vm_radix_insert(&new_object->cache, m))
- vm_page_cache_turn_free(m);
- }
- mtx_unlock(&vm_page_queue_free_mtx);
-}
-
-/*
- * Returns TRUE if a cached page is associated with the given object and
- * offset, and FALSE otherwise.
- *
- * The object must be locked.
- */
-boolean_t
-vm_page_is_cached(vm_object_t object, vm_pindex_t pindex)
-{
- vm_page_t m;
-
- /*
- * Insertion into an object's collection of cached pages requires the
- * object to be locked. Therefore, if the object is locked and the
- * object's collection is empty, there is no need to acquire the free
- * page queues lock in order to prove that the specified page doesn't
- * exist.
- */
- VM_OBJECT_ASSERT_WLOCKED(object);
- if (__predict_true(vm_object_cache_is_empty(object)))
- return (FALSE);
- mtx_lock(&vm_page_queue_free_mtx);
- m = vm_page_cache_lookup(object, pindex);
- mtx_unlock(&vm_page_queue_free_mtx);
- return (m != NULL);
-}
-
-/*
* vm_page_alloc:
*
* Allocate and return a page that is associated with the specified
@@ -1610,9 +1471,6 @@ vm_page_is_cached(vm_object_t object, vm_pindex_t pindex)
* optional allocation flags:
* VM_ALLOC_COUNT(number) the number of additional pages that the caller
* intends to allocate
- * VM_ALLOC_IFCACHED return page only if it is cached
- * VM_ALLOC_IFNOTCACHED return NULL, do not reactivate if the page
- * is cached
* VM_ALLOC_NOBUSY do not exclusive busy the page
* VM_ALLOC_NODUMP do not include the page in a kernel core dump
* VM_ALLOC_NOOBJ page is not associated with an object and
@@ -1626,8 +1484,6 @@ vm_page_is_cached(vm_object_t object, vm_pindex_t pindex)
vm_page_t
vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
{
- struct vnode *vp = NULL;
- vm_object_t m_object;
vm_page_t m, mpred;
int flags, req_class;
@@ -1670,31 +1526,12 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
* Allocate from the free queue if the number of free pages
* exceeds the minimum for the request class.
*/
- if (object != NULL &&
- (m = vm_page_cache_lookup(object, pindex)) != NULL) {
- if ((req & VM_ALLOC_IFNOTCACHED) != 0) {
- mtx_unlock(&vm_page_queue_free_mtx);
- return (NULL);
- }
- if (vm_phys_unfree_page(m))
- vm_phys_set_pool(VM_FREEPOOL_DEFAULT, m, 0);
-#if VM_NRESERVLEVEL > 0
- else if (!vm_reserv_reactivate_page(m))
-#else
- else
-#endif
- panic("vm_page_alloc: cache page %p is missing"
- " from the free queue", m);
- } else if ((req & VM_ALLOC_IFCACHED) != 0) {
- mtx_unlock(&vm_page_queue_free_mtx);
- return (NULL);
#if VM_NRESERVLEVEL > 0
- } else if (object == NULL || (object->flags & (OBJ_COLORED |
+ if (object == NULL || (object->flags & (OBJ_COLORED |
OBJ_FICTITIOUS)) != OBJ_COLORED || (m =
- vm_reserv_alloc_page(object, pindex, mpred)) == NULL) {
-#else
- } else {
+ vm_reserv_alloc_page(object, pindex, mpred)) == NULL)
#endif
+ {
m = vm_phys_alloc_pages(object != NULL ?
VM_FREEPOOL_DEFAULT : VM_FREEPOOL_DIRECT, 0);
#if VM_NRESERVLEVEL > 0
@@ -1720,33 +1557,9 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
* At this point we had better have found a good page.
*/
KASSERT(m != NULL, ("vm_page_alloc: missing page"));
- KASSERT(m->queue == PQ_NONE,
- ("vm_page_alloc: page %p has unexpected queue %d", m, m->queue));
- KASSERT(m->wire_count == 0, ("vm_page_alloc: page %p is wired", m));
- KASSERT(m->hold_count == 0, ("vm_page_alloc: page %p is held", m));
- KASSERT(!vm_page_busied(m), ("vm_page_alloc: page %p is busy", m));
- KASSERT(m->dirty == 0, ("vm_page_alloc: page %p is dirty", m));
- KASSERT(pmap_page_get_memattr(m) == VM_MEMATTR_DEFAULT,
- ("vm_page_alloc: page %p has unexpected memattr %d", m,
- pmap_page_get_memattr(m)));
- if ((m->flags & PG_CACHED) != 0) {
- KASSERT((m->flags & PG_ZERO) == 0,
- ("vm_page_alloc: cached page %p is PG_ZERO", m));
- KASSERT(m->valid != 0,
- ("vm_page_alloc: cached page %p is invalid", m));
- if (m->object != object || m->pindex != pindex)
- m->valid = 0;
- m_object = m->object;
- vm_page_cache_remove(m);
- if (m_object->type == OBJT_VNODE &&
- vm_object_cache_is_empty(m_object))
- vp = m_object->handle;
- } else {
- KASSERT(m->valid == 0,
- ("vm_page_alloc: free page %p is valid", m));
- vm_phys_freecnt_adj(m, -1);
- }
+ vm_phys_freecnt_adj(m, -1);
mtx_unlock(&vm_page_queue_free_mtx);
+ vm_page_alloc_check(m);
/*
* Initialize the page. Only the PG_ZERO flag is inherited.
@@ -1778,9 +1591,6 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
if (object != NULL) {
if (vm_page_insert_after(m, object, pindex, mpred)) {
- /* See the comment below about hold count. */
- if (vp != NULL)
- vdrop(vp);
pagedaemon_wakeup();
if (req & VM_ALLOC_WIRED) {
atomic_subtract_int(&vm_cnt.v_wire_count, 1);
@@ -1801,15 +1611,6 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
m->pindex = pindex;
/*
- * The following call to vdrop() must come after the above call
- * to vm_page_insert() in case both affect the same object and
- * vnode. Otherwise, the affected vnode's hold count could
- * temporarily become zero.
- */
- if (vp != NULL)
- vdrop(vp);
-
- /*
* Don't wakeup too often - wakeup the pageout daemon when
* we would be nearly out of memory.
*/
@@ -1819,16 +1620,6 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
return (m);
}
-static void
-vm_page_alloc_contig_vdrop(struct spglist *lst)
-{
-
- while (!SLIST_EMPTY(lst)) {
- vdrop((struct vnode *)SLIST_FIRST(lst)-> plinks.s.pv);
- SLIST_REMOVE_HEAD(lst, plinks.s.ss);
- }
-}
-
/*
* vm_page_alloc_contig:
*
@@ -1873,8 +1664,6 @@ vm_page_alloc_contig(vm_object_t object, vm_pindex_t pindex, int req,
u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment,
vm_paddr_t boundary, vm_memattr_t memattr)
{
- struct vnode *drop;
- struct spglist deferred_vdrop_list;
vm_page_t m, m_tmp, m_ret;
u_int flags;
int req_class;
@@ -1900,7 +1689,6 @@ vm_page_alloc_contig(vm_object_t object, vm_pindex_t pindex, int req,
if (curproc == pageproc && req_class != VM_ALLOC_INTERRUPT)
req_class = VM_ALLOC_SYSTEM;
- SLIST_INIT(&deferred_vdrop_list);
mtx_lock(&vm_page_queue_free_mtx);
if (vm_cnt.v_free_count + vm_cnt.v_cache_count >= npages +
vm_cnt.v_free_reserved || (req_class == VM_ALLOC_SYSTEM &&
@@ -1922,17 +1710,7 @@ retry:
return (NULL);
}
if (m_ret != NULL)
- for (m = m_ret; m < &m_ret[npages]; m++) {
- drop = vm_page_alloc_init(m);
- if (drop != NULL) {
- /*
- * Enqueue the vnode for deferred vdrop().
- */
- m->plinks.s.pv = drop;
- SLIST_INSERT_HEAD(&deferred_vdrop_list, m,
- plinks.s.ss);
- }
- }
+ vm_phys_freecnt_adj(m_ret, -npages);
else {
#if VM_NRESERVLEVEL > 0
if (vm_reserv_reclaim_contig(npages, low, high, alignment,
@@ -1943,6 +1721,8 @@ retry:
mtx_unlock(&vm_page_queue_free_mtx);
if (m_ret == NULL)
return (NULL);
+ for (m = m_ret; m < &m_ret[npages]; m++)
+ vm_page_alloc_check(m);
/*
* Initialize the pages. Only the PG_ZERO flag is inherited.
@@ -1975,8 +1755,6 @@ retry:
m->oflags = VPO_UNMANAGED;
if (object != NULL) {
if (vm_page_insert(m, object, pindex)) {
- vm_page_alloc_contig_vdrop(
- &deferred_vdrop_list);
if (vm_paging_needed())
pagedaemon_wakeup();
if ((req & VM_ALLOC_WIRED) != 0)
@@ -2001,57 +1779,28 @@ retry:
pmap_page_set_memattr(m, memattr);
pindex++;
}
- vm_page_alloc_contig_vdrop(&deferred_vdrop_list);
if (vm_paging_needed())
pagedaemon_wakeup();
return (m_ret);
}
/*
- * Initialize a page that has been freshly dequeued from a freelist.
- * The caller has to drop the vnode returned, if it is not NULL.
- *
- * This function may only be used to initialize unmanaged pages.
- *
- * To be called with vm_page_queue_free_mtx held.
+ * Check a page that has been freshly dequeued from a freelist.
*/
-static struct vnode *
-vm_page_alloc_init(vm_page_t m)
+static void
+vm_page_alloc_check(vm_page_t m)
{
- struct vnode *drop;
- vm_object_t m_object;
KASSERT(m->queue == PQ_NONE,
- ("vm_page_alloc_init: page %p has unexpected queue %d",
- m, m->queue));
- KASSERT(m->wire_count == 0,
- ("vm_page_alloc_init: page %p is wired", m));
- KASSERT(m->hold_count == 0,
- ("vm_page_alloc_init: page %p is held", m));
- KASSERT(!vm_page_busied(m),
- ("vm_page_alloc_init: page %p is busy", m));
- KASSERT(m->dirty == 0,
- ("vm_page_alloc_init: page %p is dirty", m));
+ ("page %p has unexpected queue %d", m, m->queue));
+ KASSERT(m->wire_count == 0, ("page %p is wired", m));
+ KASSERT(m->hold_count == 0, ("page %p is held", m));
+ KASSERT(!vm_page_busied(m), ("page %p is busy", m));
+ KASSERT(m->dirty == 0, ("page %p is dirty", m));
KASSERT(pmap_page_get_memattr(m) == VM_MEMATTR_DEFAULT,
- ("vm_page_alloc_init: page %p has unexpected memattr %d",
+ ("page %p has unexpected memattr %d",
m, pmap_page_get_memattr(m)));
- mtx_assert(&vm_page_queue_free_mtx, MA_OWNED);
- drop = NULL;
- if ((m->flags & PG_CACHED) != 0) {
- KASSERT((m->flags & PG_ZERO) == 0,
- ("vm_page_alloc_init: cached page %p is PG_ZERO", m));
- m->valid = 0;
- m_object = m->object;
- vm_page_cache_remove(m);
- if (m_object->type == OBJT_VNODE &&
- vm_object_cache_is_empty(m_object))
- drop = m_object->handle;
- } else {
- KASSERT(m->valid == 0,
- ("vm_page_alloc_init: free page %p is valid", m));
- vm_phys_freecnt_adj(m, -1);
- }
- return (drop);
+ KASSERT(m->valid == 0, ("free page %p is valid", m));
}
/*
@@ -2077,7 +1826,6 @@ vm_page_alloc_init(vm_page_t m)
vm_page_t
vm_page_alloc_freelist(int flind, int req)
{
- struct vnode *drop;
vm_page_t m;
u_int flags;
int req_class;
@@ -2111,8 +1859,9 @@ vm_page_alloc_freelist(int flind, int req)
mtx_unlock(&vm_page_queue_free_mtx);
return (NULL);
}
- drop = vm_page_alloc_init(m);
+ vm_phys_freecnt_adj(m, -1);
mtx_unlock(&vm_page_queue_free_mtx);
+ vm_page_alloc_check(m);
/*
* Initialize the page. Only the PG_ZERO flag is inherited.
@@ -2132,8 +1881,6 @@ vm_page_alloc_freelist(int flind, int req)
}
/* Unmanaged pages don't use "act_count". */
m->oflags = VPO_UNMANAGED;
- if (drop != NULL)
- vdrop(drop);
if (vm_paging_needed())
pagedaemon_wakeup();
return (m);
@@ -2259,38 +2006,8 @@ retry:
/* Don't care: PG_NODUMP, PG_ZERO. */
if (object->type != OBJT_DEFAULT &&
object->type != OBJT_SWAP &&
- object->type != OBJT_VNODE)
+ object->type != OBJT_VNODE) {
run_ext = 0;
- else if ((m->flags & PG_CACHED) != 0 ||
- m != vm_page_lookup(object, m->pindex)) {
- /*
- * The page is cached or recently converted
- * from cached to free.
- */
-#if VM_NRESERVLEVEL > 0
- if (level >= 0) {
- /*
- * The page is reserved. Extend the
- * current run by one page.
- */
- run_ext = 1;
- } else
-#endif
- if ((order = m->order) < VM_NFREEORDER) {
- /*
- * The page is enqueued in the
- * physical memory allocator's cache/
- * free page queues. Moreover, it is
- * the first page in a power-of-two-
- * sized run of contiguous cache/free
- * pages. Add these pages to the end
- * of the current run, and jump
- * ahead.
- */
- run_ext = 1 << order;
- m_inc = 1 << order;
- } else
- run_ext = 0;
#if VM_NRESERVLEVEL > 0
} else if ((options & VPSC_NOSUPER) != 0 &&
(level = vm_reserv_level_iffullpop(m)) >= 0) {
@@ -2457,15 +2174,7 @@ retry:
object->type != OBJT_SWAP &&
object->type != OBJT_VNODE)
error = EINVAL;
- else if ((m->flags & PG_CACHED) != 0 ||
- m != vm_page_lookup(object, m->pindex)) {
- /*
- * The page is cached or recently converted
- * from cached to free.
- */
- VM_OBJECT_WUNLOCK(object);
- goto cached;
- } else if (object->memattr != VM_MEMATTR_DEFAULT)
+ else if (object->memattr != VM_MEMATTR_DEFAULT)
error = EINVAL;
else if (m->queue != PQ_NONE && !vm_page_busied(m)) {
KASSERT(pmap_page_get_memattr(m) ==
@@ -2566,7 +2275,6 @@ retry:
unlock:
VM_OBJECT_WUNLOCK(object);
} else {
-cached:
mtx_lock(&vm_page_queue_free_mtx);
order = m->order;
if (order < VM_NFREEORDER) {
@@ -2964,27 +2672,6 @@ vm_page_free_wakeup(void)
}
/*
- * Turn a cached page into a free page, by changing its attributes.
- * Keep the statistics up-to-date.
- *
- * The free page queue must be locked.
- */
-static void
-vm_page_cache_turn_free(vm_page_t m)
-{
-
- mtx_assert(&vm_page_queue_free_mtx, MA_OWNED);
-
- m->object = NULL;
- m->valid = 0;
- KASSERT((m->flags & PG_CACHED) != 0,
- ("vm_page_cache_turn_free: page %p is not cached", m));
- m->flags &= ~PG_CACHED;
- vm_cnt.v_cache_count--;
- vm_phys_freecnt_adj(m, 1);
-}
-
-/*
* vm_page_free_toq:
*
* Returns the given page to the free list,
@@ -3383,8 +3070,7 @@ retrylookup:
VM_WAIT;
VM_OBJECT_WLOCK(object);
goto retrylookup;
- } else if (m->valid != 0)
- return (m);
+ }
if (allocflags & VM_ALLOC_ZERO && (m->flags & PG_ZERO) == 0)
pmap_zero_page(m);
return (m);
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index 417d9d87a72b..8d44e65c53a0 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -326,7 +326,6 @@ extern struct mtx_padalign pa_lock[];
* Page flags. If changed at any other time than page allocation or
* freeing, the modification must be protected by the vm_page lock.
*/
-#define PG_CACHED 0x0001 /* page is cached */
#define PG_FICTITIOUS 0x0004 /* physical page doesn't exist */
#define PG_ZERO 0x0008 /* page is zeroed */
#define PG_MARKER 0x0010 /* special queue marker page */
@@ -409,8 +408,6 @@ vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa);
#define VM_ALLOC_ZERO 0x0040 /* (acfg) Try to obtain a zeroed page */
#define VM_ALLOC_NOOBJ 0x0100 /* (acg) No associated object */
#define VM_ALLOC_NOBUSY 0x0200 /* (acg) Do not busy the page */
-#define VM_ALLOC_IFCACHED 0x0400 /* (ag) Fail if page is not cached */
-#define VM_ALLOC_IFNOTCACHED 0x0800 /* (ag) Fail if page is cached */
#define VM_ALLOC_IGN_SBUSY 0x1000 /* (g) Ignore shared busy flag */
#define VM_ALLOC_NODUMP 0x2000 /* (ag) don't include in dump */
#define VM_ALLOC_SBUSY 0x4000 /* (acg) Shared busy the page */
@@ -453,8 +450,6 @@ vm_page_t vm_page_alloc_contig(vm_object_t object, vm_pindex_t pindex, int req,
vm_paddr_t boundary, vm_memattr_t memattr);
vm_page_t vm_page_alloc_freelist(int, int);
vm_page_t vm_page_grab (vm_object_t, vm_pindex_t, int);
-void vm_page_cache_free(vm_object_t, vm_pindex_t, vm_pindex_t);
-void vm_page_cache_transfer(vm_object_t, vm_pindex_t, vm_object_t);
int vm_page_try_to_free (vm_page_t);
void vm_page_deactivate (vm_page_t);
void vm_page_deactivate_noreuse(vm_page_t);
@@ -464,7 +459,6 @@ vm_page_t vm_page_find_least(vm_object_t, vm_pindex_t);
vm_page_t vm_page_getfake(vm_paddr_t paddr, vm_memattr_t memattr);
void vm_page_initfake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr);
int vm_page_insert (vm_page_t, vm_object_t, vm_pindex_t);
-boolean_t vm_page_is_cached(vm_object_t object, vm_pindex_t pindex);
void vm_page_launder(vm_page_t m);
vm_page_t vm_page_lookup (vm_object_t, vm_pindex_t);
vm_page_t vm_page_next(vm_page_t m);
diff --git a/sys/vm/vm_reserv.c b/sys/vm/vm_reserv.c
index 8bb178817e6e..5519d2fc1a03 100644
--- a/sys/vm/vm_reserv.c
+++ b/sys/vm/vm_reserv.c
@@ -908,45 +908,6 @@ vm_reserv_level_iffullpop(vm_page_t m)
}
/*
- * Prepare for the reactivation of a cached page.
- *
- * First, suppose that the given page "m" was allocated individually, i.e., not
- * as part of a reservation, and cached. Then, suppose a reservation
- * containing "m" is allocated by the same object. Although "m" and the
- * reservation belong to the same object, "m"'s pindex may not match the
- * reservation's.
- *
- * The free page queue must be locked.
- */
-boolean_t
-vm_reserv_reactivate_page(vm_page_t m)
-{
- vm_reserv_t rv;
- int index;
-
- mtx_assert(&vm_page_queue_free_mtx, MA_OWNED);
- rv = vm_reserv_from_page(m);
- if (rv->object == NULL)
- return (FALSE);
- KASSERT((m->flags & PG_CACHED) != 0,
- ("vm_reserv_reactivate_page: page %p is not cached", m));
- if (m->object == rv->object &&
- m->pindex - rv->pindex == (index = VM_RESERV_INDEX(m->object,
- m->pindex)))
- vm_reserv_populate(rv, index);
- else {
- KASSERT(rv->inpartpopq,
- ("vm_reserv_reactivate_page: reserv %p's inpartpopq is FALSE",
- rv));
- TAILQ_REMOVE(&vm_rvq_partpop, rv, partpopq);
- rv->inpartpopq = FALSE;
- /* Don't release "m" to the physical memory allocator. */
- vm_reserv_break(rv, m);
- }
- return (TRUE);
-}
-
-/*
* Breaks the given partially-populated reservation, releasing its cached and
* free pages to the physical memory allocator.
*
diff --git a/sys/vm/vm_reserv.h b/sys/vm/vm_reserv.h
index 52f6ab25477a..1a3c0a1d4914 100644
--- a/sys/vm/vm_reserv.h
+++ b/sys/vm/vm_reserv.h
@@ -56,7 +56,6 @@ void vm_reserv_init(void);
bool vm_reserv_is_page_free(vm_page_t m);
int vm_reserv_level(vm_page_t m);
int vm_reserv_level_iffullpop(vm_page_t m);
-boolean_t vm_reserv_reactivate_page(vm_page_t m);
boolean_t vm_reserv_reclaim_contig(u_long npages, vm_paddr_t low,
vm_paddr_t high, u_long alignment, vm_paddr_t boundary);
boolean_t vm_reserv_reclaim_inactive(void);
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 92c28f3098ad..b466d32e11af 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -466,10 +466,6 @@ vnode_pager_setsize(struct vnode *vp, vm_ooffset_t nsize)
* replacement from working properly.
*/
vm_page_clear_dirty(m, base, PAGE_SIZE - base);
- } else if ((nsize & PAGE_MASK) &&
- vm_page_is_cached(object, OFF_TO_IDX(nsize))) {
- vm_page_cache_free(object, OFF_TO_IDX(nsize),
- nobjsize);
}
}
object->un_pager.vnp.vnp_size = nsize;
@@ -747,6 +743,9 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
struct bufobj *bo;
struct buf *bp;
off_t foff;
+#ifdef INVARIANTS
+ off_t blkno0;
+#endif
int bsize, pagesperblock, *freecnt;
int error, before, after, rbehind, rahead, poff, i;
int bytecount, secmask;
@@ -847,6 +846,9 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
return (VM_PAGER_OK);
}
+#ifdef INVARIANTS
+ blkno0 = bp->b_blkno;
+#endif
bp->b_blkno += (foff % bsize) / DEV_BSIZE;
/* Recalculate blocks available after/before to pages. */
@@ -868,7 +870,25 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
rbehind = min(rbehind, m[0]->pindex);
rahead = min(rahead, after);
rahead = min(rahead, object->size - m[count - 1]->pindex);
- KASSERT(rbehind + rahead + count <= sizeof(bp->b_pages),
+ /*
+ * Check that total amount of pages fit into buf. Trim rbehind and
+ * rahead evenly if not.
+ */
+ if (rbehind + rahead + count > nitems(bp->b_pages)) {
+ int trim, sum;
+
+ trim = rbehind + rahead + count - nitems(bp->b_pages) + 1;
+ sum = rbehind + rahead;
+ if (rbehind == before) {
+ /* Roundup rbehind trim to block size. */
+ rbehind -= roundup(trim * rbehind / sum, pagesperblock);
+ if (rbehind < 0)
+ rbehind = 0;
+ } else
+ rbehind -= trim * rbehind / sum;
+ rahead -= trim * rahead / sum;
+ }
+ KASSERT(rbehind + rahead + count <= nitems(bp->b_pages),
("%s: behind %d ahead %d count %d", __func__,
rbehind, rahead, count));
@@ -894,8 +914,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
for (tpindex = m[0]->pindex - 1;
tpindex >= startpindex && tpindex < m[0]->pindex;
tpindex--, i++) {
- p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL |
- VM_ALLOC_IFNOTCACHED);
+ p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL);
if (p == NULL) {
/* Shift the array. */
for (int j = 0; j < i; j++)
@@ -932,8 +951,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
for (tpindex = m[count - 1]->pindex + 1;
tpindex < endpindex; i++, tpindex++) {
- p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL |
- VM_ALLOC_IFNOTCACHED);
+ p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL);
if (p == NULL)
break;
bp->b_pages[i] = p;
@@ -953,8 +971,14 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
if (a_rahead)
*a_rahead = bp->b_pgafter;
+#ifdef INVARIANTS
KASSERT(bp->b_npages <= nitems(bp->b_pages),
("%s: buf %p overflowed", __func__, bp));
+ for (int j = 1; j < bp->b_npages; j++)
+ KASSERT(bp->b_pages[j]->pindex - 1 ==
+ bp->b_pages[j - 1]->pindex,
+ ("%s: pages array not consecutive, bp %p", __func__, bp));
+#endif
/*
* Recalculate first offset and bytecount with regards to read behind.
@@ -993,6 +1017,13 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
bp->b_vp = vp;
bp->b_bcount = bp->b_bufsize = bp->b_runningbufspace = bytecount;
bp->b_iooffset = dbtob(bp->b_blkno);
+ KASSERT(IDX_TO_OFF(m[0]->pindex - bp->b_pages[0]->pindex) ==
+ (blkno0 - bp->b_blkno) * DEV_BSIZE +
+ IDX_TO_OFF(m[0]->pindex) % bsize,
+ ("wrong offsets bsize %d m[0] %ju b_pages[0] %ju "
+ "blkno0 %ju b_blkno %ju", bsize,
+ (uintmax_t)m[0]->pindex, (uintmax_t)bp->b_pages[0]->pindex,
+ (uintmax_t)blkno0, (uintmax_t)bp->b_blkno));
atomic_add_long(&runningbufspace, bp->b_runningbufspace);
PCPU_INC(cnt.v_vnodein);